@stll/folio-core 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.d.ts +2 -1
- package/dist/ai-edits/apply.js +693 -63
- package/dist/ai-edits/block-identity.d.ts +4 -0
- package/dist/ai-edits/block-identity.js +9 -0
- package/dist/ai-edits/blockRange.d.ts +28 -1
- package/dist/ai-edits/blockRange.js +68 -2
- package/dist/ai-edits/clean-text.js +2 -1
- package/dist/ai-edits/headless.d.ts +4 -4
- package/dist/ai-edits/headless.js +9 -9
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.d.ts +7 -7
- package/dist/ai-edits/read.js +110 -3
- package/dist/ai-edits/snapshot.js +21 -3
- package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
- package/dist/ai-edits/table-cell-mutations.js +238 -0
- package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
- package/dist/ai-edits/table-mutation-plan.js +90 -0
- package/dist/ai-edits/table-row-column-mutations.d.ts +108 -0
- package/dist/ai-edits/table-row-column-mutations.js +300 -0
- package/dist/ai-edits/table-targets.d.ts +32 -0
- package/dist/ai-edits/table-targets.js +70 -0
- package/dist/ai-edits/types.d.ts +62 -1
- package/dist/ai-edits/word-diff.js +21 -0
- package/dist/compat/eigenpal.d.ts +3 -3
- package/dist/compat/eigenpal.js +3 -3
- package/dist/content-controls/mutateContentControls.js +1 -1
- package/dist/controller/activeEditorStory.d.ts +36 -0
- package/dist/controller/activeEditorStory.js +30 -0
- package/dist/controller/contentControlWidgetController.d.ts +55 -0
- package/dist/controller/contentControlWidgetController.js +141 -0
- package/dist/controller/fontReadiness.js +2 -0
- package/dist/controller/headerFooterEditorManager.js +2 -2
- package/dist/controller/hiddenEditorApi.js +2 -2
- package/dist/controller/hiddenEditorManager.d.ts +12 -1
- package/dist/controller/hiddenEditorManager.js +44 -12
- package/dist/controller/layoutPipeline.d.ts +2 -0
- package/dist/controller/layoutPipeline.js +17 -2
- package/dist/controller/noteEditorManager.d.ts +36 -0
- package/dist/controller/noteEditorManager.js +210 -0
- package/dist/document-operations.d.ts +43 -11
- package/dist/document-operations.js +186 -18
- package/dist/docx/blockContentParser.js +21 -7
- package/dist/docx/commentParser.js +6 -1
- package/dist/docx/commentRangeIntegrity.d.ts +6 -0
- package/dist/docx/commentRangeIntegrity.js +186 -0
- package/dist/docx/conformance.js +62 -1
- package/dist/docx/documentGrid.d.ts +8 -0
- package/dist/docx/documentGrid.js +8 -0
- package/dist/docx/drawingUtils.js +1 -1
- package/dist/docx/encryption/agileDecryption.js +12 -2
- package/dist/docx/encryption/compoundFile.js +6 -1
- package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
- package/dist/docx/encryption/encryptionInfo.js +18 -2
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/ensureParaIds.js +8 -7
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/groupDrawingParser.js +10 -5
- package/dist/docx/hyperlinkParser.js +1 -1
- package/dist/docx/imageParser.js +10 -6
- package/dist/docx/metadataPrivacy.js +17 -3
- package/dist/docx/notePropertiesParser.js +1 -1
- package/dist/docx/numberingParser.js +1 -1
- package/dist/docx/paragraphParser.js +70 -61
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/parser.js +3 -3
- package/dist/docx/rezip.js +20 -9
- package/dist/docx/runParser.js +17 -6
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sectionParser.js +18 -5
- package/dist/docx/selectiveSave.js +5 -1
- package/dist/docx/selectiveXmlPatch.d.ts +22 -1
- package/dist/docx/selectiveXmlPatch.js +61 -1
- package/dist/docx/serializer/blockSdtSerializer.js +3 -2
- package/dist/docx/serializer/commentSerializer.js +5 -6
- package/dist/docx/serializer/documentSerializer.js +2 -2
- package/dist/docx/serializer/headerFooterSerializer.js +2 -2
- package/dist/docx/serializer/noteSerializer.js +2 -2
- package/dist/docx/serializer/paragraphSerializer.js +23 -15
- package/dist/docx/serializer/runSerializer.js +25 -21
- package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
- package/dist/docx/serializer/stylesSerializer.js +1 -1
- package/dist/docx/serializer/tableSerializer.d.ts +5 -4
- package/dist/docx/serializer/tableSerializer.js +26 -20
- package/dist/docx/serializer/xmlUtils.d.ts +13 -1
- package/dist/docx/serializer/xmlUtils.js +27 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
- package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
- package/dist/docx/server/boundedArchive.d.ts +14 -3
- package/dist/docx/server/boundedArchive.js +56 -11
- package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
- package/dist/docx/server/extractDocxText.js +55 -8
- package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
- package/dist/docx/server/inspectDocxPackage.js +217 -0
- package/dist/docx/server/validateDocxConformance.d.ts +41 -0
- package/dist/docx/server/validateDocxConformance.js +336 -0
- package/dist/docx/settingsParser.js +26 -3
- package/dist/docx/shapeParser.js +1 -1
- package/dist/docx/styleParser.js +4 -2
- package/dist/docx/tableParser.d.ts +8 -1
- package/dist/docx/tableParser.js +31 -10
- package/dist/docx/textBoxParser.d.ts +3 -3
- package/dist/docx/textBoxParser.js +16 -12
- package/dist/docx/unzip.js +1 -0
- package/dist/docx/vmlImageParser.js +11 -3
- package/dist/docx/xmlParser.js +11 -1
- package/dist/docx/xmlSafety.d.ts +5 -0
- package/dist/docx/xmlSafety.js +9 -0
- package/dist/fields/resolveFieldValues.js +1 -3
- package/dist/fonts/embeddedFonts.d.ts +33 -5
- package/dist/fonts/embeddedFonts.js +37 -8
- package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
- package/dist/i18n/messages/catalogs.gen.js +17 -0
- package/dist/i18n/messages/messages.gen.d.ts +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
- package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +151 -20
- package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
- package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
- package/dist/layout-bridge/engine/clickToPosition.js +2 -2
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +58 -30
- package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
- package/dist/layout-engine/justificationCompatibility.js +8 -0
- package/dist/layout-engine/keep-together.js +11 -1
- package/dist/layout-engine/measure/cache.js +23 -5
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +56 -37
- package/dist/layout-engine/measure/measureBlocks.js +15 -4
- package/dist/layout-engine/measure/measureContainer.js +1 -1
- package/dist/layout-engine/measure/measureHelpers.d.ts +11 -2
- package/dist/layout-engine/measure/measureHelpers.js +15 -4
- package/dist/layout-engine/measure/measureParagraph.js +85 -25
- package/dist/layout-engine/measure/measureProvider.js +4 -3
- package/dist/layout-engine/measure/tableCellFlow.js +5 -2
- package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
- package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
- package/dist/layout-engine/paginator.js +5 -1
- package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
- package/dist/layout-engine/paragraphSpacing.js +107 -13
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +48 -15
- package/dist/layout-painter/registry/modules/textBox.js +5 -1
- package/dist/layout-painter/renderImage.d.ts +12 -1
- package/dist/layout-painter/renderImage.js +21 -4
- package/dist/layout-painter/renderPage.d.ts +5 -2
- package/dist/layout-painter/renderPage.js +59 -14
- package/dist/layout-painter/renderParagraph.js +55 -15
- package/dist/layout-painter/renderTable.d.ts +5 -1
- package/dist/layout-painter/renderTable.js +7 -3
- package/dist/layout-painter/renderTextBox.d.ts +2 -1
- package/dist/layout-painter/renderTextBox.js +25 -14
- package/dist/layout-painter/renderWatermark.d.ts +1 -1
- package/dist/layout-painter/renderWatermark.js +2 -1
- package/dist/managers/DocumentLoaderManager.js +1 -1
- package/dist/markdown/fromMarkdown.js +1 -1
- package/dist/model.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +175 -18
- package/dist/prosemirror/commands/comments.d.ts +79 -4
- package/dist/prosemirror/commands/comments.js +622 -13
- package/dist/prosemirror/commands/contentControls.js +1 -1
- package/dist/prosemirror/commands/hyperlink.js +15 -1
- package/dist/prosemirror/commands/image.js +7 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
- package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
- package/dist/prosemirror/commentIdAllocator.js +13 -3
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +404 -62
- package/dist/prosemirror/conversion/index.js +1 -1
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
- package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
- package/dist/prosemirror/conversion/toProseDoc.js +364 -103
- package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
- package/dist/prosemirror/extensions/StarterKit.js +6 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +6 -2
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +15 -2
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +70 -11
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +14 -6
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
- package/dist/prosemirror/index.d.ts +1 -1
- package/dist/prosemirror/index.js +1 -1
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +36 -10
- package/dist/prosemirror/plugins/contentControlWidgets.js +128 -94
- package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
- package/dist/prosemirror/plugins/revisionIds.js +57 -0
- package/dist/prosemirror/plugins/selectionTracker.js +1 -0
- package/dist/prosemirror/plugins/suggestionMode.js +5 -4
- package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
- package/dist/prosemirror/runFormattingMarkNames.js +40 -0
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +30 -3
- package/dist/prosemirror/schema/marks.js +15 -0
- package/dist/prosemirror/schema/nodes.d.ts +111 -6
- package/dist/prosemirror/selectionState.js +1 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
- package/dist/prosemirror/tableCellMergeRevision.js +22 -0
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
- package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
- package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
- package/dist/prosemirror/validation.js +9 -1
- package/dist/render-dom/RemoteSelectionOverlay.js +2 -2
- package/dist/server.d.ts +7 -3
- package/dist/server.js +7 -3
- package/dist/utils/clipboard.d.ts +10 -1
- package/dist/utils/clipboard.js +33 -6
- package/dist/utils/colorResolver.d.ts +8 -1
- package/dist/utils/colorResolver.js +35 -5
- package/dist/utils/fontFamilyMerge.js +9 -11
- package/dist/utils/fontLoader.js +3 -2
- package/dist/utils/fontResolver.d.ts +2 -1
- package/dist/utils/fontResolver.js +31 -7
- package/dist/utils/fontWeights.d.ts +1 -1
- package/dist/utils/fontWeights.js +1 -1
- package/dist/utils/hexId.d.ts +11 -1
- package/dist/utils/hexId.js +11 -1
- package/dist/utils/paragraphFormattingMerge.js +1 -0
- package/dist/utils/sanitizeImageSrc.d.ts +21 -0
- package/dist/utils/sanitizeImageSrc.js +30 -0
- package/dist/utils/stripXmlDeclarations.d.ts +11 -0
- package/dist/utils/stripXmlDeclarations.js +35 -0
- package/dist/version-comparison.d.ts +22 -2
- package/dist/version-comparison.js +41 -12
- package/dist/watermark/index.d.ts +11 -1
- package/dist/watermark/index.js +22 -1
- package/package.json +3 -2
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { OUTLINE_STYLE_CSS_ALIASES } from "../../types/documentEnumValues.js";
|
|
2
|
+
import { directionToBidi } from "../paragraphDirection.js";
|
|
3
|
+
import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
|
|
2
4
|
import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
|
|
3
|
-
import { pixelsToEmu } from "../../utils/units.js";
|
|
4
5
|
import { numPrEqual } from "../../docx/numberingParser.js";
|
|
6
|
+
import { pixelsToEmu } from "../../utils/units.js";
|
|
5
7
|
import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBase.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
+
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
9
|
+
import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
|
|
8
10
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
9
11
|
import { runShadingAttrsToShading } from "./runShadingMark.js";
|
|
12
|
+
import { sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
|
|
13
|
+
import { textFormattingToMarks } from "./toProseDoc.js";
|
|
14
|
+
import { Fragment } from "prosemirror-model";
|
|
10
15
|
//#region src/prosemirror/conversion/fromProseDoc.ts
|
|
11
16
|
function normalizeShapeOutlineStyle(style) {
|
|
12
17
|
if (!style) return;
|
|
@@ -69,12 +74,122 @@ function fromProseDoc(pmDoc, baseDocument) {
|
|
|
69
74
|
};
|
|
70
75
|
return { package: { document: documentBody } };
|
|
71
76
|
}
|
|
77
|
+
const isSuggestedMark = (mark) => mark.attrs["provenance"] === "suggested";
|
|
78
|
+
const hasSuggestedInsertion = (marks) => marks.some((mark) => mark.type.name === "insertion" && isSuggestedMark(mark));
|
|
79
|
+
/**
|
|
80
|
+
* Compute the mark set an inline node should keep once its suggested tracked
|
|
81
|
+
* changes are stripped. Suggested deletions are dropped so their text survives
|
|
82
|
+
* as plain content; a suggested `runPropertyChange` is dropped and the run's
|
|
83
|
+
* live formatting is reverted to the recorded `previousFormatting`.
|
|
84
|
+
*
|
|
85
|
+
* Returns the input array unchanged when there is nothing to strip so callers
|
|
86
|
+
* can skip rebuilding the node.
|
|
87
|
+
*/
|
|
88
|
+
function stripSuggestedInlineMarks(marks) {
|
|
89
|
+
const hasSuggestedDeletion = marks.some((mark) => mark.type.name === "deletion" && isSuggestedMark(mark));
|
|
90
|
+
const suggestedRunPropertyChange = marks.find((mark) => mark.type.name === "runPropertyChange" && isSuggestedMark(mark));
|
|
91
|
+
if (!hasSuggestedDeletion && !suggestedRunPropertyChange) return marks;
|
|
92
|
+
let next = marks.filter((mark) => !((mark.type.name === "deletion" || mark.type.name === "runPropertyChange") && isSuggestedMark(mark)));
|
|
93
|
+
if (suggestedRunPropertyChange) {
|
|
94
|
+
const previousFormatting = expectRunPropertyChangeMarkAttrs(suggestedRunPropertyChange).changes.at(0)?.previousFormatting;
|
|
95
|
+
next = next.filter((mark) => !RUN_FORMATTING_MARK_NAMES.has(mark.type.name));
|
|
96
|
+
for (const restored of textFormattingToMarks(previousFormatting)) next = restored.addToSet(next);
|
|
97
|
+
}
|
|
98
|
+
return next;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Compute the node attrs a block/structural node keeps once its suggested
|
|
102
|
+
* revision markers are neutralized. Returns `null` when nothing changes.
|
|
103
|
+
*
|
|
104
|
+
* - a suggested `trDel` / `cellMarker` (insertion or deletion) is cleared so
|
|
105
|
+
* the row/cell serializes as though the proposed change never happened;
|
|
106
|
+
* merge markers never carry suggestion provenance (structurally excluded);
|
|
107
|
+
* - suggested INSERT markers are handled by the caller, which drops the whole
|
|
108
|
+
* node instead of clearing an attr.
|
|
109
|
+
*
|
|
110
|
+
* Reads go through the typed attr readers (adapter-boundary convention).
|
|
111
|
+
*/
|
|
112
|
+
function stripSuggestedNodeAttrs(node) {
|
|
113
|
+
const name = node.type.name;
|
|
114
|
+
if (name === "tableRow") {
|
|
115
|
+
const rowAttrs = expectTableRowAttrs(node);
|
|
116
|
+
if (rowAttrs.trDel?.provenance === "suggested") return {
|
|
117
|
+
...rowAttrs,
|
|
118
|
+
trDel: null
|
|
119
|
+
};
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (name === "tableCell" || name === "tableHeader") {
|
|
123
|
+
const cellAttrs = expectTableCellAttrs(node);
|
|
124
|
+
const marker = cellAttrs.cellMarker;
|
|
125
|
+
if (marker && marker.kind !== "merge" && marker.info.provenance === "suggested") return {
|
|
126
|
+
...cellAttrs,
|
|
127
|
+
cellMarker: null
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Whether a block/structural node is a suggested whole-node INSERT and must be
|
|
134
|
+
* dropped from serialization entirely (paragraph, table, row, or column cell).
|
|
135
|
+
*/
|
|
136
|
+
function isSuggestedInsertedNode(node) {
|
|
137
|
+
const name = node.type.name;
|
|
138
|
+
if (name === "paragraph") return expectParagraphAttrs(node)._suggestedInsert != null;
|
|
139
|
+
if (name === "table") return expectTableAttrs(node)._suggestedInsert != null;
|
|
140
|
+
if (name === "tableRow") return expectTableRowAttrs(node).trIns?.provenance === "suggested";
|
|
141
|
+
if (name === "tableCell" || name === "tableHeader") {
|
|
142
|
+
const marker = expectTableCellAttrs(node).cellMarker;
|
|
143
|
+
return marker?.kind === "ins" && marker.info.provenance === "suggested";
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Recursively rewrite a ProseMirror node tree, removing every suggested
|
|
149
|
+
* tracked change. Returns `null` when the node itself must be dropped: a
|
|
150
|
+
* suggested-inserted inline node, or a suggested-inserted block/row/cell.
|
|
151
|
+
* Surviving block nodes are rebuilt with their suggested delete/merge markers
|
|
152
|
+
* cleared and their children stripped.
|
|
153
|
+
*/
|
|
154
|
+
function mapSuggestionStrippedNode(node) {
|
|
155
|
+
if (node.isInline) {
|
|
156
|
+
if (hasSuggestedInsertion(node.marks)) return null;
|
|
157
|
+
const marks = stripSuggestedInlineMarks(node.marks);
|
|
158
|
+
return marks === node.marks ? node : node.mark(marks);
|
|
159
|
+
}
|
|
160
|
+
if (isSuggestedInsertedNode(node)) return null;
|
|
161
|
+
const nextAttrs = stripSuggestedNodeAttrs(node);
|
|
162
|
+
const children = [];
|
|
163
|
+
let changed = nextAttrs !== null;
|
|
164
|
+
node.forEach((child) => {
|
|
165
|
+
const mapped = mapSuggestionStrippedNode(child);
|
|
166
|
+
if (mapped === null) {
|
|
167
|
+
changed = true;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (mapped !== child) changed = true;
|
|
171
|
+
children.push(mapped);
|
|
172
|
+
});
|
|
173
|
+
if (!changed) return node;
|
|
174
|
+
const content = Fragment.fromArray(children);
|
|
175
|
+
return nextAttrs === null ? node.copy(content) : node.type.create(nextAttrs, content, node.marks);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Strip suggested (AI-proposed) tracked changes from a document so it
|
|
179
|
+
* serializes as though the suggestion never happened. See the call site in
|
|
180
|
+
* {@link extractBlocks} for why this is the sole serialization boundary.
|
|
181
|
+
*/
|
|
182
|
+
function stripSuggestedProvenance(doc) {
|
|
183
|
+
return mapSuggestionStrippedNode(doc) ?? doc;
|
|
184
|
+
}
|
|
72
185
|
/**
|
|
73
186
|
* Extract block content (paragraphs, tables, block SDTs) from a ProseMirror
|
|
74
187
|
* document.
|
|
75
188
|
*/
|
|
76
|
-
function extractBlocks(
|
|
189
|
+
function extractBlocks(inputDoc) {
|
|
190
|
+
const pmDoc = stripSuggestedProvenance(inputDoc);
|
|
77
191
|
const blocks = [];
|
|
192
|
+
const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
|
|
78
193
|
const documentCounts = buildDocumentTrackedChangeCounts(pmDoc);
|
|
79
194
|
let pendingPageBreaks = 0;
|
|
80
195
|
let previousStandaloneTextBox = null;
|
|
@@ -96,7 +211,7 @@ function extractBlocks(pmDoc) {
|
|
|
96
211
|
return;
|
|
97
212
|
}
|
|
98
213
|
if (node.type.name === "paragraph") {
|
|
99
|
-
const paragraph = convertPMParagraph(node, documentCounts);
|
|
214
|
+
const paragraph = convertPMParagraph(node, documentCounts, textBoxAnchorMarkers);
|
|
100
215
|
prependPageBreaks(paragraph, pendingPageBreaks);
|
|
101
216
|
pendingPageBreaks = 0;
|
|
102
217
|
blocks.push(paragraph);
|
|
@@ -108,7 +223,8 @@ function extractBlocks(pmDoc) {
|
|
|
108
223
|
} else if (node.type.name === "textBox") {
|
|
109
224
|
previousStandaloneTextBox = appendTextBoxBlock(blocks, node, {
|
|
110
225
|
pendingPageBreaks,
|
|
111
|
-
previousStandaloneTextBox
|
|
226
|
+
previousStandaloneTextBox,
|
|
227
|
+
textBoxAnchorMarkers
|
|
112
228
|
});
|
|
113
229
|
pendingPageBreaks = 0;
|
|
114
230
|
} else if (node.type.name === "blockSdt") {
|
|
@@ -118,6 +234,7 @@ function extractBlocks(pmDoc) {
|
|
|
118
234
|
}
|
|
119
235
|
});
|
|
120
236
|
if (pendingPageBreaks > 0 && !appendPendingPageBreaksToPreviousParagraph()) flushPendingPageBreaks();
|
|
237
|
+
removeUnresolvedTextBoxAnchors(blocks, textBoxAnchorMarkers);
|
|
121
238
|
return blocks;
|
|
122
239
|
}
|
|
123
240
|
function convertPMBlockSdt(node) {
|
|
@@ -176,11 +293,18 @@ function appendTextBoxBlock(blocks, node, options) {
|
|
|
176
293
|
const previousBlock = blocks.at(-1);
|
|
177
294
|
if (attrs._docxPlacement === "inlineWithPrevious" && previousBlock?.type === "paragraph") {
|
|
178
295
|
appendPageBreaks(previousBlock, options.pendingPageBreaks);
|
|
179
|
-
|
|
296
|
+
const anchorId = attrs._docxAnchorId;
|
|
297
|
+
const anchorMarker = anchorId ? options.textBoxAnchorMarkers.get(anchorId) : void 0;
|
|
298
|
+
const textBoxRun = findTextBoxShapeRun(paragraph.content);
|
|
299
|
+
if (anchorId && anchorMarker && textBoxRun && replaceTextBoxAnchorInBlocks(blocks, anchorMarker, textBoxRun)) {
|
|
300
|
+
options.textBoxAnchorMarkers.delete(anchorId);
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
if (!mergeTextBoxIntoTrailingInlineSdts(previousBlock, paragraph, attrs._docxInlineSdts ?? [])) previousBlock.content.push(...paragraph.content);
|
|
180
304
|
return null;
|
|
181
305
|
}
|
|
182
306
|
if (attrs._docxPlacement === "standalone" && attrs._docxGroupId && options.previousStandaloneTextBox?.groupId === attrs._docxGroupId) {
|
|
183
|
-
options.previousStandaloneTextBox.paragraph.content.push(...paragraph.content);
|
|
307
|
+
if (!mergeTextBoxIntoTrailingInlineSdts(options.previousStandaloneTextBox.paragraph, paragraph, attrs._docxInlineSdts ?? [])) options.previousStandaloneTextBox.paragraph.content.push(...paragraph.content);
|
|
184
308
|
return options.previousStandaloneTextBox;
|
|
185
309
|
}
|
|
186
310
|
prependPageBreaks(paragraph, options.pendingPageBreaks);
|
|
@@ -190,6 +314,108 @@ function appendTextBoxBlock(blocks, node, options) {
|
|
|
190
314
|
groupId: attrs._docxGroupId
|
|
191
315
|
} : null;
|
|
192
316
|
}
|
|
317
|
+
function mergeTextBoxIntoTrailingInlineSdts(target, incoming, inlineSdts) {
|
|
318
|
+
if (inlineSdts.length === 0 || incoming.content.length !== 1) return false;
|
|
319
|
+
const incomingSdt = incoming.content.at(0);
|
|
320
|
+
const outerAttrs = inlineSdts.at(0);
|
|
321
|
+
if (!outerAttrs || incomingSdt?.type !== "inlineSdt") return false;
|
|
322
|
+
let targetSdt;
|
|
323
|
+
for (let index = target.content.length - 1; index >= 0; index -= 1) {
|
|
324
|
+
const content = target.content[index];
|
|
325
|
+
if (content?.type === "inlineSdt" && sdtPropertiesMatchAttrs(content.properties, outerAttrs)) {
|
|
326
|
+
targetSdt = content;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (!targetSdt) return false;
|
|
331
|
+
return mergeInlineSdtNodes(targetSdt, incomingSdt, inlineSdts, 0);
|
|
332
|
+
}
|
|
333
|
+
function mergeInlineSdtNodes(target, incoming, inlineSdts, index) {
|
|
334
|
+
const attrs = inlineSdts[index];
|
|
335
|
+
if (!attrs || !sdtPropertiesMatchAttrs(target.properties, attrs) || !sdtPropertiesMatchAttrs(incoming.properties, attrs)) return false;
|
|
336
|
+
if (index === inlineSdts.length - 1) {
|
|
337
|
+
target.content.push(...incoming.content);
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
const incomingNested = incoming.content.at(0);
|
|
341
|
+
const nestedAttrs = inlineSdts[index + 1];
|
|
342
|
+
if (!nestedAttrs || incomingNested?.type !== "inlineSdt") return false;
|
|
343
|
+
let targetNested;
|
|
344
|
+
for (let nestedIndex = target.content.length - 1; nestedIndex >= 0; nestedIndex -= 1) {
|
|
345
|
+
const content = target.content[nestedIndex];
|
|
346
|
+
if (content?.type === "inlineSdt" && sdtPropertiesMatchAttrs(content.properties, nestedAttrs)) {
|
|
347
|
+
targetNested = content;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (!targetNested) {
|
|
352
|
+
target.content.push(incomingNested);
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
return mergeInlineSdtNodes(targetNested, incomingNested, inlineSdts, index + 1);
|
|
356
|
+
}
|
|
357
|
+
function findTextBoxShapeRun(content) {
|
|
358
|
+
for (const item of content) {
|
|
359
|
+
if (item.type === "run") {
|
|
360
|
+
if (item.content.some((runContent) => runContent.type === "shape" && runContent.shape.shapeType === "textBox")) return item;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (item.type === "inlineSdt" || item.type === "hyperlink" || item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
364
|
+
const run = findTextBoxShapeRun(item.type === "hyperlink" ? item.children : item.content);
|
|
365
|
+
if (run) return run;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function replaceTextBoxAnchorInBlocks(blocks, marker, textBoxRun) {
|
|
370
|
+
for (const block of blocks) {
|
|
371
|
+
if (block.type === "paragraph") {
|
|
372
|
+
if (editTextBoxAnchorInContent(block.content, marker, textBoxRun)) return true;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (block.type === "table") {
|
|
376
|
+
for (const row of block.rows) for (const cell of row.cells) if (replaceTextBoxAnchorInBlocks(cell.content, marker, textBoxRun)) return true;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (replaceTextBoxAnchorInBlocks(block.content, marker, textBoxRun)) return true;
|
|
380
|
+
}
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
function editTextBoxAnchorInContent(content, marker, replacement) {
|
|
384
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
385
|
+
const item = content[index];
|
|
386
|
+
if (item === marker) {
|
|
387
|
+
content.splice(index, 1, ...replacement ? [replacement] : []);
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
let nestedContent;
|
|
391
|
+
if (item?.type === "hyperlink") nestedContent = item.children;
|
|
392
|
+
else if (item?.type === "inlineSdt" || item?.type === "insertion" || item?.type === "deletion" || item?.type === "moveFrom" || item?.type === "moveTo") nestedContent = item.content;
|
|
393
|
+
if (!nestedContent) continue;
|
|
394
|
+
const hadContent = nestedContent.length > 0;
|
|
395
|
+
if (editTextBoxAnchorInContent(nestedContent, marker, replacement)) {
|
|
396
|
+
if (!replacement && hadContent && nestedContent.length === 0) content.splice(index, 1);
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
function removeUnresolvedTextBoxAnchors(blocks, markers) {
|
|
403
|
+
for (const marker of markers.values()) removeTextBoxAnchorFromBlocks(blocks, marker);
|
|
404
|
+
}
|
|
405
|
+
function removeTextBoxAnchorFromBlocks(blocks, marker) {
|
|
406
|
+
for (const block of blocks) {
|
|
407
|
+
if (block.type === "paragraph") {
|
|
408
|
+
if (editTextBoxAnchorInContent(block.content, marker)) return true;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
if (block.type === "table") {
|
|
412
|
+
for (const row of block.rows) for (const cell of row.cells) if (removeTextBoxAnchorFromBlocks(cell.content, marker)) return true;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (removeTextBoxAnchorFromBlocks(block.content, marker)) return true;
|
|
416
|
+
}
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
193
419
|
/**
|
|
194
420
|
* Inverse of toProseDoc's listRendering → list* attrs flattening. Markdown
|
|
195
421
|
* export (`toMarkdown`) and re-layout of the rebuilt Document key off
|
|
@@ -254,9 +480,9 @@ function appendPageBreaks(paragraph, count) {
|
|
|
254
480
|
/**
|
|
255
481
|
* Convert a ProseMirror paragraph node to our Paragraph type
|
|
256
482
|
*/
|
|
257
|
-
function convertPMParagraph(node, documentCounts) {
|
|
483
|
+
function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers) {
|
|
258
484
|
const attrs = expectParagraphAttrs(node);
|
|
259
|
-
let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0);
|
|
485
|
+
let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0, textBoxAnchorMarkers, attrs.renderedPageBreakBefore === true);
|
|
260
486
|
const bookmarks = attrs.bookmarks;
|
|
261
487
|
if (bookmarks && bookmarks.length > 0) {
|
|
262
488
|
const starts = bookmarks.map((b) => ({
|
|
@@ -344,6 +570,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
344
570
|
else delete result.styleId;
|
|
345
571
|
assignBooleanToggle(result, attrs, orig, "pageBreakBefore");
|
|
346
572
|
assignBooleanToggle(result, attrs, orig, "widowControl");
|
|
573
|
+
assignBooleanToggle(result, attrs, orig, "snapToGrid");
|
|
347
574
|
assignBooleanToggle(result, attrs, orig, "kinsoku");
|
|
348
575
|
assignBooleanToggle(result, attrs, orig, "overflowPunctuation");
|
|
349
576
|
assignBooleanToggle(result, attrs, orig, "suppressAutoHyphens");
|
|
@@ -356,7 +583,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
356
583
|
}
|
|
357
584
|
const outlineLevel = Reflect.get(attrs, "outlineLevel");
|
|
358
585
|
const bidi = directionToBidi(attrs.direction);
|
|
359
|
-
if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || 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;
|
|
586
|
+
if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || 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;
|
|
360
587
|
const f = {};
|
|
361
588
|
if (attrs.alignment) f.alignment = attrs.alignment;
|
|
362
589
|
if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
|
|
@@ -365,6 +592,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
365
592
|
if (afterAutospacingEdited) f.afterAutospacing = false;
|
|
366
593
|
if (attrs.lineSpacing) f.lineSpacing = attrs.lineSpacing;
|
|
367
594
|
if (attrs.lineSpacingRule) f.lineSpacingRule = attrs.lineSpacingRule;
|
|
595
|
+
if (attrs.snapToGrid != null) f.snapToGrid = attrs.snapToGrid;
|
|
368
596
|
if (attrs.spacingExplicit) f.spacingExplicit = attrs.spacingExplicit;
|
|
369
597
|
if (attrs.indentLeft) f.indentLeft = attrs.indentLeft;
|
|
370
598
|
if (attrs.indentRight) f.indentRight = attrs.indentRight;
|
|
@@ -391,13 +619,14 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
391
619
|
* Coalesces consecutive text with the same marks into single Runs
|
|
392
620
|
* for efficient DOCX representation.
|
|
393
621
|
*/
|
|
394
|
-
function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
|
|
622
|
+
function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false) {
|
|
395
623
|
const content = [];
|
|
396
624
|
const sortedEmptyHyperlinks = (emptyHyperlinks ?? []).map((attrs, order) => ({
|
|
397
625
|
attrs,
|
|
398
626
|
order
|
|
399
627
|
})).toSorted((left, right) => left.attrs.offset - right.attrs.offset || left.order - right.order);
|
|
400
628
|
let nextEmptyHyperlink = 0;
|
|
629
|
+
let leadingRenderedPageBreakPending = skipLeadingRenderedPageBreak;
|
|
401
630
|
let currentRun = null;
|
|
402
631
|
let currentMarksKey = null;
|
|
403
632
|
let currentHyperlink = null;
|
|
@@ -455,11 +684,54 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
|
|
|
455
684
|
}
|
|
456
685
|
};
|
|
457
686
|
const processInlineNode = (node, offset) => {
|
|
687
|
+
if (node.type.name === "renderedPageBreak" && leadingRenderedPageBreakPending) {
|
|
688
|
+
leadingRenderedPageBreakPending = false;
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
leadingRenderedPageBreakPending = false;
|
|
458
692
|
syncCommentRanges(node, offset);
|
|
459
693
|
const linkMark = node.marks.find((m) => m.type.name === "hyperlink");
|
|
460
694
|
const noteRefMark = node.marks.find((m) => m.type.name === "footnoteRef");
|
|
461
695
|
const insertionMark = node.marks.find((m) => m.type.name === "insertion");
|
|
462
696
|
const deletionMark = node.marks.find((m) => m.type.name === "deletion");
|
|
697
|
+
if (node.type.name === "textBoxAnchor") {
|
|
698
|
+
flushCurrentInline();
|
|
699
|
+
if (!textBoxAnchorMarkers) return;
|
|
700
|
+
const { anchorId } = expectTextBoxAnchorAttrs(node);
|
|
701
|
+
const marker = {
|
|
702
|
+
type: "run",
|
|
703
|
+
content: []
|
|
704
|
+
};
|
|
705
|
+
if (textBoxAnchorMarkers.has(anchorId)) return;
|
|
706
|
+
textBoxAnchorMarkers.set(anchorId, marker);
|
|
707
|
+
const anchoredContent = linkMark ? {
|
|
708
|
+
...createHyperlink(linkMark),
|
|
709
|
+
children: [marker]
|
|
710
|
+
} : marker;
|
|
711
|
+
const changeMark = insertionMark ?? deletionMark;
|
|
712
|
+
if (!changeMark) {
|
|
713
|
+
content.push(anchoredContent);
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
const changeAttrs = expectTrackedChangeMarkAttrs(changeMark);
|
|
717
|
+
const info = {
|
|
718
|
+
id: changeAttrs.revisionId,
|
|
719
|
+
author: changeAttrs.author || "Unknown",
|
|
720
|
+
...changeAttrs.date ? { date: changeAttrs.date } : {},
|
|
721
|
+
...changeAttrs.initials ? { initials: changeAttrs.initials } : {}
|
|
722
|
+
};
|
|
723
|
+
if (insertionMark) content.push({
|
|
724
|
+
type: changeAttrs.moveKind === "moveTo" ? "moveTo" : "insertion",
|
|
725
|
+
info,
|
|
726
|
+
content: [anchoredContent]
|
|
727
|
+
});
|
|
728
|
+
else content.push({
|
|
729
|
+
type: changeAttrs.moveKind === "moveFrom" ? "moveFrom" : "deletion",
|
|
730
|
+
info,
|
|
731
|
+
content: [anchoredContent]
|
|
732
|
+
});
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
463
735
|
if (insertionMark || deletionMark) {
|
|
464
736
|
flushCurrentInline();
|
|
465
737
|
const changeMark = insertionMark ?? deletionMark;
|
|
@@ -467,30 +739,35 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
|
|
|
467
739
|
const changeAttrs = expectTrackedChangeMarkAttrs(changeMark);
|
|
468
740
|
const run = createTrackedChangeRun(node, node.marks.filter((m) => m.type.name !== "insertion" && m.type.name !== "deletion"));
|
|
469
741
|
if (!run) return;
|
|
742
|
+
const trackedContent = linkMark ? {
|
|
743
|
+
...createHyperlink(linkMark),
|
|
744
|
+
children: [run]
|
|
745
|
+
} : run;
|
|
470
746
|
const info = {
|
|
471
747
|
id: changeAttrs.revisionId,
|
|
472
748
|
author: changeAttrs.author || "Unknown"
|
|
473
749
|
};
|
|
474
750
|
if (changeAttrs.date) info.date = changeAttrs.date;
|
|
751
|
+
if (changeAttrs.initials) info.initials = changeAttrs.initials;
|
|
475
752
|
if (insertionMark) if (changeAttrs.moveKind === "moveTo") content.push({
|
|
476
753
|
type: "moveTo",
|
|
477
754
|
info,
|
|
478
|
-
content: [
|
|
755
|
+
content: [trackedContent]
|
|
479
756
|
});
|
|
480
757
|
else content.push({
|
|
481
758
|
type: "insertion",
|
|
482
759
|
info,
|
|
483
|
-
content: [
|
|
760
|
+
content: [trackedContent]
|
|
484
761
|
});
|
|
485
762
|
else if (changeAttrs.moveKind === "moveFrom") content.push({
|
|
486
763
|
type: "moveFrom",
|
|
487
764
|
info,
|
|
488
|
-
content: [
|
|
765
|
+
content: [trackedContent]
|
|
489
766
|
});
|
|
490
767
|
else content.push({
|
|
491
768
|
type: "deletion",
|
|
492
769
|
info,
|
|
493
|
-
content: [
|
|
770
|
+
content: [trackedContent]
|
|
494
771
|
});
|
|
495
772
|
return;
|
|
496
773
|
}
|
|
@@ -530,12 +807,15 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
|
|
|
530
807
|
} else if (node.type.name === "tab") {
|
|
531
808
|
flushCurrentInline();
|
|
532
809
|
content.push(createTabRun());
|
|
810
|
+
} else if (node.type.name === "renderedPageBreak") {
|
|
811
|
+
flushCurrentInline();
|
|
812
|
+
content.push(createRenderedPageBreakRun());
|
|
533
813
|
} else if (node.type.name === "field") {
|
|
534
814
|
flushCurrentInline();
|
|
535
815
|
content.push(createFieldFromNode(node, node.marks));
|
|
536
816
|
} else if (node.type.name === "sdt") {
|
|
537
817
|
flushCurrentInline();
|
|
538
|
-
content.push(createInlineSdtFromNode(node));
|
|
818
|
+
content.push(createInlineSdtFromNode(node, textBoxAnchorMarkers));
|
|
539
819
|
} else if (node.type.name === "math") {
|
|
540
820
|
flushCurrentInline();
|
|
541
821
|
content.push(createMathFromNode(node));
|
|
@@ -576,7 +856,7 @@ function createTrackedChangeRun(node, marks) {
|
|
|
576
856
|
if (noteRefMark) return createNoteReferenceRun(noteRefMark, marks);
|
|
577
857
|
if (node.isText) {
|
|
578
858
|
const formatting = marksToTextFormatting(marks);
|
|
579
|
-
|
|
859
|
+
const run = {
|
|
580
860
|
type: "run",
|
|
581
861
|
content: node.text ? [{
|
|
582
862
|
type: "text",
|
|
@@ -584,11 +864,14 @@ function createTrackedChangeRun(node, marks) {
|
|
|
584
864
|
}] : [],
|
|
585
865
|
...Object.keys(formatting).length > 0 ? { formatting } : {}
|
|
586
866
|
};
|
|
867
|
+
restoreRunPropertyChanges(run, marks);
|
|
868
|
+
return run;
|
|
587
869
|
}
|
|
588
870
|
if (node.type.name === "hardBreak") return createBreakRun(readHardBreakType(node));
|
|
589
871
|
if (node.type.name === "image") return createImageRun(node);
|
|
590
872
|
if (node.type.name === "shape") return createShapeRun(node);
|
|
591
873
|
if (node.type.name === "tab") return createTabRun();
|
|
874
|
+
if (node.type.name === "renderedPageBreak") return createRenderedPageBreakRun();
|
|
592
875
|
return null;
|
|
593
876
|
}
|
|
594
877
|
function createEmptyHyperlink(attrs) {
|
|
@@ -699,6 +982,10 @@ function addNodeToHyperlink(hyperlink, node) {
|
|
|
699
982
|
hyperlink.children.push(createTabRun(nonLinkMarks));
|
|
700
983
|
return;
|
|
701
984
|
}
|
|
985
|
+
if (node.type.name === "renderedPageBreak") {
|
|
986
|
+
hyperlink.children.push(createRenderedPageBreakRun());
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
702
989
|
if (node.type.name === "image") {
|
|
703
990
|
hyperlink.children.push(createImageRun(node));
|
|
704
991
|
return;
|
|
@@ -736,8 +1023,16 @@ function createRunFromText(text, marks) {
|
|
|
736
1023
|
}]
|
|
737
1024
|
};
|
|
738
1025
|
if (formatting) run.formatting = formatting;
|
|
1026
|
+
restoreRunPropertyChanges(run, marks);
|
|
739
1027
|
return run;
|
|
740
1028
|
}
|
|
1029
|
+
function restoreRunPropertyChanges(run, marks) {
|
|
1030
|
+
const changeMark = marks.find((mark) => mark.type.name === "runPropertyChange");
|
|
1031
|
+
if (!changeMark) return;
|
|
1032
|
+
const { changes } = expectRunPropertyChangeMarkAttrs(changeMark);
|
|
1033
|
+
if (changes.length === 0) return;
|
|
1034
|
+
run.propertyChanges = [...changes];
|
|
1035
|
+
}
|
|
741
1036
|
function getRunFormattingFromMarks(marks) {
|
|
742
1037
|
if (!marks || marks.length === 0) return;
|
|
743
1038
|
const formatting = marksToTextFormatting(marks);
|
|
@@ -769,6 +1064,12 @@ function createBreakRun(breakType = "textWrapping", marks) {
|
|
|
769
1064
|
if (formatting) run.formatting = formatting;
|
|
770
1065
|
return run;
|
|
771
1066
|
}
|
|
1067
|
+
function createRenderedPageBreakRun() {
|
|
1068
|
+
return {
|
|
1069
|
+
type: "run",
|
|
1070
|
+
content: [{ type: "renderedPageBreak" }]
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
772
1073
|
function readHardBreakType(node) {
|
|
773
1074
|
return expectHardBreakAttrs(node).breakType ?? "textWrapping";
|
|
774
1075
|
}
|
|
@@ -848,41 +1149,13 @@ function createMathFromNode(node) {
|
|
|
848
1149
|
/**
|
|
849
1150
|
* Create an InlineSdt from a PM sdt node
|
|
850
1151
|
*/
|
|
851
|
-
function createInlineSdtFromNode(node) {
|
|
852
|
-
const attrs = expectSdtAttrs(node);
|
|
853
|
-
const properties = { sdtType: attrs.sdtType };
|
|
854
|
-
if (attrs.alias) properties.alias = attrs.alias;
|
|
855
|
-
if (attrs.tag) properties.tag = attrs.tag;
|
|
856
|
-
if (typeof attrs.id === "number") properties.id = attrs.id;
|
|
857
|
-
if (attrs.lock) properties.lock = attrs.lock;
|
|
858
|
-
if (attrs.placeholder) properties.placeholder = attrs.placeholder;
|
|
859
|
-
if (attrs.showingPlaceholder !== void 0) properties.showingPlaceholder = attrs.showingPlaceholder;
|
|
860
|
-
if (attrs.dateFormat) properties.dateFormat = attrs.dateFormat;
|
|
861
|
-
if (attrs.dateValueISO) properties.dateValueISO = attrs.dateValueISO;
|
|
862
|
-
if (attrs.listItems) properties.listItems = parseSdtListItems(attrs.listItems);
|
|
863
|
-
if (typeof attrs.dropdownLastValue === "string") properties.dropdownLastValue = attrs.dropdownLastValue;
|
|
864
|
-
if (typeof attrs.checked === "boolean") properties.checked = attrs.checked;
|
|
865
|
-
if (attrs.rawPropertiesXml) properties.rawPropertiesXml = attrs.rawPropertiesXml;
|
|
866
|
-
if (attrs.rawEndPropertiesXml) properties.rawEndPropertiesXml = attrs.rawEndPropertiesXml;
|
|
1152
|
+
function createInlineSdtFromNode(node, textBoxAnchorMarkers) {
|
|
867
1153
|
return {
|
|
868
1154
|
type: "inlineSdt",
|
|
869
|
-
properties,
|
|
870
|
-
content: extractParagraphContent(node).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 === "mathEquation")
|
|
1155
|
+
properties: sdtPropertiesFromAttrs(expectSdtAttrs(node)),
|
|
1156
|
+
content: extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers).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")
|
|
871
1157
|
};
|
|
872
1158
|
}
|
|
873
|
-
function parseSdtListItems(rawItems) {
|
|
874
|
-
const parsed = JSON.parse(rawItems);
|
|
875
|
-
if (!Array.isArray(parsed)) throw new TypeError("Invalid ProseMirror sdt attrs: listItems is not an array");
|
|
876
|
-
return parsed.map((item) => {
|
|
877
|
-
if (!item || typeof item !== "object" || Array.isArray(item)) throw new TypeError("Invalid ProseMirror sdt attrs: listItems contains an invalid item");
|
|
878
|
-
const itemAttrs = item;
|
|
879
|
-
if (typeof itemAttrs.displayText !== "string" || typeof itemAttrs.value !== "string") throw new TypeError("Invalid ProseMirror sdt attrs: listItems contains an invalid item");
|
|
880
|
-
return {
|
|
881
|
-
displayText: itemAttrs.displayText,
|
|
882
|
-
value: itemAttrs.value
|
|
883
|
-
};
|
|
884
|
-
});
|
|
885
|
-
}
|
|
886
1159
|
/**
|
|
887
1160
|
* Create a Run containing an image
|
|
888
1161
|
*/
|
|
@@ -1399,6 +1672,24 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
|
|
|
1399
1672
|
const rowFormatting = tableRowAttrsToFormatting(attrs);
|
|
1400
1673
|
if (rowFormatting) row.formatting = rowFormatting;
|
|
1401
1674
|
if (Array.isArray(attrs.trPrChange) && attrs.trPrChange.length > 0) row.propertyChanges = [...attrs.trPrChange];
|
|
1675
|
+
if (attrs.trIns) row.structuralChange = {
|
|
1676
|
+
type: "tableRowInsertion",
|
|
1677
|
+
info: {
|
|
1678
|
+
id: attrs.trIns.revisionId,
|
|
1679
|
+
author: attrs.trIns.author,
|
|
1680
|
+
...attrs.trIns.date != null && { date: attrs.trIns.date },
|
|
1681
|
+
...attrs.trIns.initials != null && { initials: attrs.trIns.initials }
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
else if (attrs.trDel) row.structuralChange = {
|
|
1685
|
+
type: "tableRowDeletion",
|
|
1686
|
+
info: {
|
|
1687
|
+
id: attrs.trDel.revisionId,
|
|
1688
|
+
author: attrs.trDel.author,
|
|
1689
|
+
...attrs.trDel.date != null && { date: attrs.trDel.date },
|
|
1690
|
+
...attrs.trDel.initials != null && { initials: attrs.trDel.initials }
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1402
1693
|
return row;
|
|
1403
1694
|
}
|
|
1404
1695
|
function createVerticalMergeContinuationCell(colspan) {
|
|
@@ -1450,19 +1741,22 @@ function tableRowAttrsToFormatting(attrs) {
|
|
|
1450
1741
|
function convertPMTableCell(node, documentCounts) {
|
|
1451
1742
|
const attrs = expectTableCellAttrs(node);
|
|
1452
1743
|
const content = [];
|
|
1744
|
+
const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
|
|
1453
1745
|
let previousStandaloneTextBox = null;
|
|
1454
1746
|
node.forEach((contentNode) => {
|
|
1455
1747
|
if (contentNode.type.name === "paragraph") {
|
|
1456
|
-
content.push(convertPMParagraph(contentNode, documentCounts));
|
|
1748
|
+
content.push(convertPMParagraph(contentNode, documentCounts, textBoxAnchorMarkers));
|
|
1457
1749
|
previousStandaloneTextBox = null;
|
|
1458
1750
|
} else if (contentNode.type.name === "table") {
|
|
1459
1751
|
content.push(convertPMTable(contentNode, documentCounts));
|
|
1460
1752
|
previousStandaloneTextBox = null;
|
|
1461
1753
|
} else if (contentNode.type.name === "textBox") previousStandaloneTextBox = appendTextBoxBlock(content, contentNode, {
|
|
1462
1754
|
pendingPageBreaks: 0,
|
|
1463
|
-
previousStandaloneTextBox
|
|
1755
|
+
previousStandaloneTextBox,
|
|
1756
|
+
textBoxAnchorMarkers
|
|
1464
1757
|
});
|
|
1465
1758
|
});
|
|
1759
|
+
removeUnresolvedTextBoxAnchors(content, textBoxAnchorMarkers);
|
|
1466
1760
|
const cell = {
|
|
1467
1761
|
type: "tableCell",
|
|
1468
1762
|
content
|
|
@@ -1470,8 +1764,27 @@ function convertPMTableCell(node, documentCounts) {
|
|
|
1470
1764
|
const cellFormatting = tableCellAttrsToFormatting(attrs);
|
|
1471
1765
|
if (cellFormatting) cell.formatting = cellFormatting;
|
|
1472
1766
|
if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
|
|
1767
|
+
if (attrs.cellMarker) {
|
|
1768
|
+
const info = {
|
|
1769
|
+
id: attrs.cellMarker.info.revisionId,
|
|
1770
|
+
author: attrs.cellMarker.info.author,
|
|
1771
|
+
...attrs.cellMarker.info.date != null && { date: attrs.cellMarker.info.date },
|
|
1772
|
+
...attrs.cellMarker.info.initials != null && { initials: attrs.cellMarker.info.initials }
|
|
1773
|
+
};
|
|
1774
|
+
if (attrs.cellMarker.kind === "merge") cell.structuralChange = {
|
|
1775
|
+
type: "tableCellMerge",
|
|
1776
|
+
info,
|
|
1777
|
+
...attrs.cellMarker.verticalMerge !== void 0 ? { verticalMerge: attrs.cellMarker.verticalMerge } : {},
|
|
1778
|
+
...attrs.cellMarker.verticalMergeOriginal !== void 0 ? { verticalMergeOriginal: attrs.cellMarker.verticalMergeOriginal } : {}
|
|
1779
|
+
};
|
|
1780
|
+
else cell.structuralChange = {
|
|
1781
|
+
type: attrs.cellMarker.kind === "ins" ? "tableCellInsertion" : "tableCellDeletion",
|
|
1782
|
+
info
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1473
1785
|
return cell;
|
|
1474
1786
|
}
|
|
1787
|
+
const standaloneTableCellFromProseMirror = (node) => convertPMTableCell(node);
|
|
1475
1788
|
const cellShadingFromAttrs = (attrs) => attrs.backgroundColor ? { fill: { rgb: attrs.backgroundColor } } : { pattern: "nil" };
|
|
1476
1789
|
function tableCellAttrsToFormatting(attrs) {
|
|
1477
1790
|
const backgroundChanged = attrs.backgroundColor !== attrs._resolvedBackgroundColor;
|
|
@@ -1479,6 +1792,7 @@ function tableCellAttrsToFormatting(attrs) {
|
|
|
1479
1792
|
const orig = attrs._originalFormatting;
|
|
1480
1793
|
const result = { ...orig };
|
|
1481
1794
|
if (attrs.colspan > 1) result.gridSpan = attrs.colspan;
|
|
1795
|
+
else delete result.gridSpan;
|
|
1482
1796
|
if (attrs.rowspan > 1) result.vMerge = "restart";
|
|
1483
1797
|
else if (result.vMerge === "restart" && !attrs._preserveVMergeRestart) delete result.vMerge;
|
|
1484
1798
|
const cellWidth = attrs.width;
|
|
@@ -1517,9 +1831,10 @@ function tableCellAttrsToFormatting(attrs) {
|
|
|
1517
1831
|
*/
|
|
1518
1832
|
function convertPMTextBox(node) {
|
|
1519
1833
|
const attrs = expectTextBoxAttrs(node);
|
|
1520
|
-
const
|
|
1834
|
+
const childBlocks = [];
|
|
1521
1835
|
node.forEach((child) => {
|
|
1522
|
-
if (child.type.name === "paragraph")
|
|
1836
|
+
if (child.type.name === "paragraph") childBlocks.push(convertPMParagraph(child));
|
|
1837
|
+
else if (child.type.name === "table") childBlocks.push(convertPMTable(child));
|
|
1523
1838
|
});
|
|
1524
1839
|
const shape = {
|
|
1525
1840
|
type: "shape",
|
|
@@ -1529,7 +1844,7 @@ function convertPMTextBox(node) {
|
|
|
1529
1844
|
height: attrs.height ? pixelsToEmu(attrs.height) : 0
|
|
1530
1845
|
},
|
|
1531
1846
|
textBody: {
|
|
1532
|
-
content:
|
|
1847
|
+
content: childBlocks.length > 0 ? childBlocks : [{
|
|
1533
1848
|
type: "paragraph",
|
|
1534
1849
|
content: []
|
|
1535
1850
|
}],
|
|
@@ -1561,16 +1876,43 @@ function convertPMTextBox(node) {
|
|
|
1561
1876
|
if (wrap) shape.wrap = wrap;
|
|
1562
1877
|
const position = imagePositionFromAttrs(attrs.position);
|
|
1563
1878
|
if (position) shape.position = position;
|
|
1564
|
-
|
|
1565
|
-
type: "
|
|
1879
|
+
const run = {
|
|
1880
|
+
type: "run",
|
|
1566
1881
|
content: [{
|
|
1567
|
-
type: "
|
|
1568
|
-
|
|
1569
|
-
type: "shape",
|
|
1570
|
-
shape
|
|
1571
|
-
}]
|
|
1882
|
+
type: "shape",
|
|
1883
|
+
shape
|
|
1572
1884
|
}]
|
|
1573
1885
|
};
|
|
1886
|
+
const trackedChange = attrs._docxTrackedChange;
|
|
1887
|
+
const inlineSdts = attrs._docxInlineSdts ?? [];
|
|
1888
|
+
if (inlineSdts.length > 0) {
|
|
1889
|
+
let wrapped = trackedChange ? {
|
|
1890
|
+
type: trackedChange.type,
|
|
1891
|
+
info: trackedChange.info,
|
|
1892
|
+
content: [run]
|
|
1893
|
+
} : run;
|
|
1894
|
+
for (let index = inlineSdts.length - 1; index >= 0; index -= 1) {
|
|
1895
|
+
const sdtAttrs = inlineSdts[index];
|
|
1896
|
+
if (!sdtAttrs) continue;
|
|
1897
|
+
wrapped = {
|
|
1898
|
+
type: "inlineSdt",
|
|
1899
|
+
properties: sdtPropertiesFromAttrs(sdtAttrs),
|
|
1900
|
+
content: [wrapped]
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
return {
|
|
1904
|
+
type: "paragraph",
|
|
1905
|
+
content: [wrapped]
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
return {
|
|
1909
|
+
type: "paragraph",
|
|
1910
|
+
content: trackedChange ? [{
|
|
1911
|
+
type: trackedChange.type,
|
|
1912
|
+
info: trackedChange.info,
|
|
1913
|
+
content: [run]
|
|
1914
|
+
}] : [run]
|
|
1915
|
+
};
|
|
1574
1916
|
}
|
|
1575
1917
|
/**
|
|
1576
1918
|
* Update a Document with content from a ProseMirror document
|
|
@@ -1590,4 +1932,4 @@ function proseDocToBlocks(pmDoc) {
|
|
|
1590
1932
|
return extractBlocks(pmDoc);
|
|
1591
1933
|
}
|
|
1592
1934
|
//#endregion
|
|
1593
|
-
export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, updateDocumentContent };
|
|
1935
|
+
export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, standaloneTableCellFromProseMirror, updateDocumentContent };
|