@stll/folio-core 0.37.1 → 0.37.3
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/headless.d.ts +24 -1
- package/dist/ai-edits/headless.js +108 -71
- package/dist/ai-edits/read.d.ts +9 -1
- package/dist/ai-edits/read.js +34 -16
- package/dist/ai-edits/snapshot.d.ts +7 -5
- package/dist/ai-edits/snapshot.js +39 -12
- package/dist/ai-edits/table-cell-mutations.js +10 -5
- package/dist/ai-edits/table-template.js +19 -5
- package/dist/compare/compare.d.ts +2 -3
- package/dist/compare/compare.js +41 -64
- package/dist/compare/content-alignment.js +0 -1
- package/dist/compare/scenario.d.ts +11 -2
- package/dist/compare/scenario.js +6 -2
- package/dist/controller/hiddenEditorManager.js +11 -0
- package/dist/controller/layoutPipeline.js +1 -1
- package/dist/display-list/build/textBoxPrimitives.js +34 -1
- package/dist/display-list/dom/renderDisplayListToDom.js +5 -2
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/display-list/types.d.ts +8 -4
- package/dist/docx/paragraphPropertySource.d.ts +82 -2
- package/dist/docx/paragraphPropertySource.js +569 -3
- package/dist/docx/parser.js +9 -0
- package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
- package/dist/docx/server/materializeYjsDocx.js +21 -2
- package/dist/headless-layout.js +1 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +7 -1
- package/dist/layout-bridge/convert/headerFooterLayout.js +20 -3
- package/dist/layout-bridge/convert/toFlowBlocks.js +43 -12
- package/dist/layout-engine/index.js +20 -10
- package/dist/layout-engine/measure/measureBlocks.d.ts +7 -3
- package/dist/layout-engine/measure/measureBlocks.js +10 -7
- package/dist/layout-engine/measure/measureParagraph.d.ts +2 -0
- package/dist/layout-engine/measure/measureParagraph.js +1 -1
- package/dist/layout-engine/paginator.d.ts +1 -1
- package/dist/layout-engine/paginator.js +41 -4
- package/dist/layout-engine/textBoxFlow.d.ts +2 -0
- package/dist/layout-engine/textBoxFlow.js +9 -5
- package/dist/layout-engine/types.d.ts +6 -0
- package/dist/layout-painter/documentColors.d.ts +10 -1
- package/dist/layout-painter/documentColors.js +16 -1
- package/dist/layout-painter/renderParagraph.js +9 -24
- package/dist/layout-painter/renderTable.js +3 -3
- package/dist/layout-painter/renderTextBox.js +2 -1
- package/dist/pdf/pageSpace.d.ts +12 -1
- package/dist/pdf/pageSpace.js +24 -1
- package/dist/pdf/paint.js +2 -2
- package/dist/prosemirror/attrs/index.js +19 -8
- package/dist/prosemirror/commands/comments.js +12 -3
- package/dist/prosemirror/commands/tableCellMergeResolution.js +18 -11
- package/dist/prosemirror/conversion/fromProseDoc.js +94 -21
- package/dist/prosemirror/conversion/toProseDoc.js +100 -8
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +5 -1
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +132 -41
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
- package/dist/prosemirror/schema/nodes.d.ts +3 -1
- package/dist/prosemirror/yjsParagraphSourceContract.d.ts +9 -0
- package/dist/prosemirror/yjsParagraphSourceContract.js +26 -0
- package/dist/utils/rotationBoundingBox.d.ts +5 -1
- package/dist/utils/rotationBoundingBox.js +9 -1
- package/package.json +2 -2
|
@@ -604,6 +604,8 @@ type TableRow = {
|
|
|
604
604
|
isHeader?: boolean;
|
|
605
605
|
/** `w:cantSplit`: keep this row in one flow region. */
|
|
606
606
|
cantSplit?: boolean;
|
|
607
|
+
/** A leading authored page break in a cell advances the whole row. */
|
|
608
|
+
breakBefore?: "page";
|
|
607
609
|
hidden?: boolean;
|
|
608
610
|
};
|
|
609
611
|
/**
|
|
@@ -802,6 +804,8 @@ type TextBoxBlock = {
|
|
|
802
804
|
outlineColor?: string;
|
|
803
805
|
/** Outline dash style, or `"none"` for an explicit no-outline. */
|
|
804
806
|
outlineStyle?: OutlineStyleAttr;
|
|
807
|
+
/** DrawingML rotation and/or flips, serialized as CSS transform functions. */
|
|
808
|
+
transform?: string;
|
|
805
809
|
/** Internal padding */
|
|
806
810
|
margins?: {
|
|
807
811
|
top: number;
|
|
@@ -1032,6 +1036,8 @@ type FragmentBase = {
|
|
|
1032
1036
|
*/
|
|
1033
1037
|
type ParagraphFragment = FragmentBase & {
|
|
1034
1038
|
kind: "paragraph";
|
|
1039
|
+
/** Structural PM carrier that must not make an otherwise blank page visible. */
|
|
1040
|
+
paginationRole?: "empty-carrier";
|
|
1035
1041
|
/** First line index (inclusive) from the measure. */
|
|
1036
1042
|
fromLine: number;
|
|
1037
1043
|
/** Last line index (exclusive) from the measure. */
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
//#region src/layout-painter/documentColors.d.ts
|
|
2
|
+
declare const AUTHORED_BACKGROUND_COLOR_VAR = "--doc-authored-background-color";
|
|
3
|
+
declare const AUTHORED_TEXT_COLOR_VAR = "--doc-run-color";
|
|
4
|
+
/** Paint a document text color and expose it to the dark-mode color transform. */
|
|
5
|
+
declare const setAuthoredTextColor: (style: CSSStyleDeclaration, color: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Paint an OOXML background and retain its authored color for dark-mode adaptation.
|
|
8
|
+
* The custom property is presentation-only; serialization still uses the model value.
|
|
9
|
+
*/
|
|
10
|
+
declare const setAuthoredBackgroundColor: (style: CSSStyleDeclaration, color: string) => void;
|
|
2
11
|
declare function getAutomaticTextColorForBackground(backgroundColor: string | undefined): string | undefined;
|
|
3
12
|
//#endregion
|
|
4
|
-
export { getAutomaticTextColorForBackground };
|
|
13
|
+
export { AUTHORED_BACKGROUND_COLOR_VAR, AUTHORED_TEXT_COLOR_VAR, getAutomaticTextColorForBackground, setAuthoredBackgroundColor, setAuthoredTextColor };
|
|
@@ -5,6 +5,21 @@ const WHITE_TEXT_COLOR = "#FFFFFF";
|
|
|
5
5
|
const BLACK_LUMINANCE = 0;
|
|
6
6
|
const WHITE_LUMINANCE = 1;
|
|
7
7
|
const CONTRAST_OFFSET = .05;
|
|
8
|
+
const AUTHORED_BACKGROUND_COLOR_VAR = "--doc-authored-background-color";
|
|
9
|
+
const AUTHORED_TEXT_COLOR_VAR = "--doc-run-color";
|
|
10
|
+
/** Paint a document text color and expose it to the dark-mode color transform. */
|
|
11
|
+
const setAuthoredTextColor = (style, color) => {
|
|
12
|
+
style.color = color;
|
|
13
|
+
style.setProperty(AUTHORED_TEXT_COLOR_VAR, color);
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Paint an OOXML background and retain its authored color for dark-mode adaptation.
|
|
17
|
+
* The custom property is presentation-only; serialization still uses the model value.
|
|
18
|
+
*/
|
|
19
|
+
const setAuthoredBackgroundColor = (style, color) => {
|
|
20
|
+
style.backgroundColor = color;
|
|
21
|
+
style.setProperty(AUTHORED_BACKGROUND_COLOR_VAR, color);
|
|
22
|
+
};
|
|
8
23
|
function normalizeHexColor(color) {
|
|
9
24
|
const trimmed = color.trim();
|
|
10
25
|
if (!HEX_COLOR_RE.test(trimmed)) return null;
|
|
@@ -37,4 +52,4 @@ function getAutomaticTextColorForBackground(backgroundColor) {
|
|
|
37
52
|
return contrastRatio(luminance, BLACK_LUMINANCE) >= contrastRatio(luminance, WHITE_LUMINANCE) ? BLACK_TEXT_COLOR : WHITE_TEXT_COLOR;
|
|
38
53
|
}
|
|
39
54
|
//#endregion
|
|
40
|
-
export { getAutomaticTextColorForBackground };
|
|
55
|
+
export { AUTHORED_BACKGROUND_COLOR_VAR, AUTHORED_TEXT_COLOR_VAR, getAutomaticTextColorForBackground, setAuthoredBackgroundColor, setAuthoredTextColor };
|
|
@@ -19,7 +19,7 @@ import { SCRIPT_CLASS, hasCjk, hasComplexScript, segmentByScript } from "../util
|
|
|
19
19
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
20
20
|
import { borderStrokeToCss, resolveParagraphBorderHorizontalOutsets } from "./borderStroke.js";
|
|
21
21
|
import { planCursiveJoiners, withCursiveJoiners } from "./cursiveJoiners.js";
|
|
22
|
-
import { getAutomaticTextColorForBackground } from "./documentColors.js";
|
|
22
|
+
import { getAutomaticTextColorForBackground, setAuthoredBackgroundColor, setAuthoredTextColor } from "./documentColors.js";
|
|
23
23
|
import { applyImageBorder, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, wrapImageWithCrop } from "./renderImage.js";
|
|
24
24
|
import { resolveImageLineAlign } from "./renderUtils.js";
|
|
25
25
|
import { applySdtDataAttrs } from "./sdtBoundary.js";
|
|
@@ -124,12 +124,6 @@ const DEFAULT_BLACK_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["000000", "000"
|
|
|
124
124
|
const SUGGESTION_COLOR_CSS = "var(--suggestion-color, #6d3bd6)";
|
|
125
125
|
const SUGGESTION_TINT_CSS = "var(--suggestion-bg, color-mix(in oklch, #6d3bd6 12%, transparent))";
|
|
126
126
|
const SUGGESTION_TINT_LAYER_CSS = `linear-gradient(${SUGGESTION_TINT_CSS}, ${SUGGESTION_TINT_CSS})`;
|
|
127
|
-
const RUN_BACKGROUND_TEXT_COLOR_VAR = "--doc-run-background-text-color";
|
|
128
|
-
const setRunBackgroundTextColor = (element, color) => {
|
|
129
|
-
element.classList.add("docx-run-background-text");
|
|
130
|
-
element.style.setProperty(RUN_BACKGROUND_TEXT_COLOR_VAR, color);
|
|
131
|
-
};
|
|
132
|
-
const hasRunBackgroundTextSurface = (run) => Boolean(run.highlight ?? run.shading) && !run.isInsertion && !run.isDeletion && !(run.commentIds !== void 0 && run.commentIds.length > 0);
|
|
133
127
|
function normalizeTextColorValue(color) {
|
|
134
128
|
return color.trim().toLowerCase().replace(/^#/u, "");
|
|
135
129
|
}
|
|
@@ -180,8 +174,7 @@ function applyRunStyles(element, run) {
|
|
|
180
174
|
let hasExplicitTextColor = false;
|
|
181
175
|
const textColor = getRenderableTextColor(run);
|
|
182
176
|
if (textColor) {
|
|
183
|
-
element.style
|
|
184
|
-
element.style.setProperty("--doc-run-color", textColor);
|
|
177
|
+
setAuthoredTextColor(element.style, textColor);
|
|
185
178
|
hasExplicitTextColor = true;
|
|
186
179
|
}
|
|
187
180
|
if (run.letterSpacing) element.style.letterSpacing = `${run.letterSpacing}px`;
|
|
@@ -219,13 +212,11 @@ function applyRunStyles(element, run) {
|
|
|
219
212
|
}
|
|
220
213
|
const runBackground = run.highlight ?? run.shading;
|
|
221
214
|
if (runBackground) {
|
|
222
|
-
element.style
|
|
215
|
+
setAuthoredBackgroundColor(element.style, runBackground);
|
|
223
216
|
const hasTrackedChangeColor = run.isInsertion || run.isDeletion;
|
|
224
217
|
const hasCommentHighlight = run.commentIds !== void 0 && run.commentIds.length > 0;
|
|
225
218
|
const automaticTextColor = hasExplicitTextColor || hasTrackedChangeColor || hasCommentHighlight ? void 0 : getAutomaticTextColorForBackground(runBackground);
|
|
226
|
-
if (automaticTextColor) element.style
|
|
227
|
-
const backgroundTextColor = hasExplicitTextColor ? textColor : automaticTextColor;
|
|
228
|
-
if (backgroundTextColor && hasRunBackgroundTextSurface(run)) setRunBackgroundTextColor(element, backgroundTextColor);
|
|
219
|
+
if (automaticTextColor) setAuthoredTextColor(element.style, automaticTextColor);
|
|
229
220
|
}
|
|
230
221
|
const decorations = [];
|
|
231
222
|
let explicitDecorationStyle = false;
|
|
@@ -378,15 +369,9 @@ function renderTextRun(run, doc, options) {
|
|
|
378
369
|
});
|
|
379
370
|
if (!run.hyperlink.noDefaultStyle) {
|
|
380
371
|
const hyperlinkColor = getHyperlinkTextColor(run, span.style.color);
|
|
381
|
-
anchor.style
|
|
372
|
+
setAuthoredTextColor(anchor.style, hyperlinkColor);
|
|
382
373
|
anchor.style.textDecoration = "underline";
|
|
383
|
-
span.style
|
|
384
|
-
anchor.style.setProperty("--doc-run-color", hyperlinkColor);
|
|
385
|
-
span.style.setProperty("--doc-run-color", hyperlinkColor);
|
|
386
|
-
if (hasRunBackgroundTextSurface(run)) {
|
|
387
|
-
setRunBackgroundTextColor(span, hyperlinkColor);
|
|
388
|
-
setRunBackgroundTextColor(anchor, hyperlinkColor);
|
|
389
|
-
}
|
|
374
|
+
setAuthoredTextColor(span.style, hyperlinkColor);
|
|
390
375
|
}
|
|
391
376
|
span.append(anchor);
|
|
392
377
|
} else appendPaintedText({
|
|
@@ -1295,7 +1280,7 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
1295
1280
|
}
|
|
1296
1281
|
const authoredEndpoint = currentX + tabResult.width + followingWidthForCheck;
|
|
1297
1282
|
const activeContentRightEdge = options?.contentWidthPx === void 0 ? void 0 : options.contentWidthPx - (options.floatingMargins?.rightMargin ?? 0);
|
|
1298
|
-
const preservesAuthoredEndStop = activeContentRightEdge !== void 0 && tabResult.alignment === "end" && authoredEndpoint <= activeContentRightEdge + RIGHT_EDGE_EPSILON_PX;
|
|
1283
|
+
const preservesAuthoredEndStop = activeContentRightEdge !== void 0 && tabResult.alignment === "end" && (options?.context?.section === "header" || options?.context?.section === "footer" || authoredEndpoint <= activeContentRightEdge + RIGHT_EDGE_EPSILON_PX);
|
|
1299
1284
|
const preservesAuthoredEndStopPastIndent = lineRightEdgeX !== void 0 && preservesAuthoredEndStop && authoredEndpoint > lineRightEdgeX + RIGHT_EDGE_EPSILON_PX;
|
|
1300
1285
|
if (lineRightEdgeX !== void 0 && options?.isRtl !== true && tabResult.alignment === "end" && !hasFollowingTab && !preservesAuthoredEndStopPastIndent && authoredEndpoint >= lineRightEdgeX - RIGHT_EDGE_EPSILON_PX) {
|
|
1301
1286
|
lineEl.style.display = "flex";
|
|
@@ -1534,9 +1519,9 @@ function renderParagraphFragment(fragment, block, measure, context, options = {}
|
|
|
1534
1519
|
}
|
|
1535
1520
|
}
|
|
1536
1521
|
if (block.attrs?.shading) {
|
|
1537
|
-
fragmentEl.style
|
|
1522
|
+
setAuthoredBackgroundColor(fragmentEl.style, block.attrs.shading);
|
|
1538
1523
|
const automaticTextColor = getAutomaticTextColorForBackground(block.attrs.shading);
|
|
1539
|
-
if (automaticTextColor) fragmentEl.style
|
|
1524
|
+
if (automaticTextColor) setAuthoredTextColor(fragmentEl.style, automaticTextColor);
|
|
1540
1525
|
}
|
|
1541
1526
|
const availableWidth = fragment.width - indentLeft - indentRight;
|
|
1542
1527
|
const paragraphEndsWithLineBreak = block.runs.at(-1)?.kind === "lineBreak";
|
|
@@ -9,7 +9,7 @@ import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
|
9
9
|
import { emuToPixels } from "../utils/units.js";
|
|
10
10
|
import { resolveAnchoredImagePosition } from "./anchoredImagePosition.js";
|
|
11
11
|
import { borderStrokeToCss, resolveCssBorderStroke } from "./borderStroke.js";
|
|
12
|
-
import { getAutomaticTextColorForBackground } from "./documentColors.js";
|
|
12
|
+
import { getAutomaticTextColorForBackground, setAuthoredBackgroundColor, setAuthoredTextColor } from "./documentColors.js";
|
|
13
13
|
import { applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs } from "./renderImage.js";
|
|
14
14
|
import { renderParagraphFragment } from "./renderParagraph.js";
|
|
15
15
|
import { renderTextBoxFragment } from "./renderTextBox.js";
|
|
@@ -394,9 +394,9 @@ function renderTableCell({ cell, cellMeasure, x, width, rowHeight, borderFlags,
|
|
|
394
394
|
if (borderFlags.drawLeft) applyBorder(cellEl, "left", cell.borders.left);
|
|
395
395
|
}
|
|
396
396
|
if (cell.background) {
|
|
397
|
-
cellEl.style
|
|
397
|
+
setAuthoredBackgroundColor(cellEl.style, cell.background);
|
|
398
398
|
const automaticTextColor = getAutomaticTextColorForBackground(cell.background);
|
|
399
|
-
if (automaticTextColor) cellEl.style
|
|
399
|
+
if (automaticTextColor) setAuthoredTextColor(cellEl.style, automaticTextColor);
|
|
400
400
|
}
|
|
401
401
|
if (cell.noWrap && !columnsPinned) cellEl.style.whiteSpace = "nowrap";
|
|
402
402
|
if (cell.verticalAlign) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { layoutTextBoxContent } from "../layout-engine/measure/textBoxParagraphLayout.js";
|
|
2
2
|
import { DEFAULT_TEXTBOX_MARGINS } from "../layout-engine/types.js";
|
|
3
|
+
import { setAuthoredBackgroundColor } from "./documentColors.js";
|
|
3
4
|
import { renderParagraphFragment } from "./renderParagraph.js";
|
|
4
5
|
import { panic } from "better-result";
|
|
5
6
|
//#region src/layout-painter/renderTextBox.ts
|
|
@@ -28,7 +29,7 @@ function renderTextBoxFragment(fragment, block, measure, context, options = {})
|
|
|
28
29
|
containerEl.style.height = `${fragment.height}px`;
|
|
29
30
|
containerEl.style.overflow = block.textWrap === "none" ? "visible" : "hidden";
|
|
30
31
|
containerEl.style.boxSizing = "border-box";
|
|
31
|
-
if (block.fillColor) containerEl.style
|
|
32
|
+
if (block.fillColor) setAuthoredBackgroundColor(containerEl.style, block.fillColor);
|
|
32
33
|
if (block.outlineWidth && block.outlineWidth > 0) {
|
|
33
34
|
const style = block.outlineStyle || "solid";
|
|
34
35
|
const color = block.outlineColor || "#000000";
|
package/dist/pdf/pageSpace.d.ts
CHANGED
|
@@ -39,5 +39,16 @@ declare const displayPointToPdf: (pageHeightPx: number, xPx: number, yPx: number
|
|
|
39
39
|
* screen, which is what a positive CSS/OOXML angle means.
|
|
40
40
|
*/
|
|
41
41
|
declare const rotationMatrix: (degrees: number, originXPx: number, originYPx: number) => PdfMatrix;
|
|
42
|
+
/**
|
|
43
|
+
* A DrawingML flip and rotation about one display-list point. CSS applies the
|
|
44
|
+
* rightmost scale first, then the rotation; this matrix does the same.
|
|
45
|
+
*/
|
|
46
|
+
declare const transformMatrix: ({ degrees, originXPx, originYPx, scaleX, scaleY }: {
|
|
47
|
+
readonly degrees: number;
|
|
48
|
+
readonly originXPx: number;
|
|
49
|
+
readonly originYPx: number;
|
|
50
|
+
readonly scaleX?: -1;
|
|
51
|
+
readonly scaleY?: -1;
|
|
52
|
+
}) => PdfMatrix;
|
|
42
53
|
//#endregion
|
|
43
|
-
export { POINTS_PER_PIXEL, PdfMatrix, applyMatrix, basePageMatrix, displayPointToPdf, pxToPt, rotationMatrix };
|
|
54
|
+
export { POINTS_PER_PIXEL, PdfMatrix, applyMatrix, basePageMatrix, displayPointToPdf, pxToPt, rotationMatrix, transformMatrix };
|
package/dist/pdf/pageSpace.js
CHANGED
|
@@ -53,5 +53,28 @@ const rotationMatrix = (degrees, originXPx, originYPx) => {
|
|
|
53
53
|
originYPx - originXPx * sin - originYPx * cos
|
|
54
54
|
];
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* A DrawingML flip and rotation about one display-list point. CSS applies the
|
|
58
|
+
* rightmost scale first, then the rotation; this matrix does the same.
|
|
59
|
+
*/
|
|
60
|
+
const transformMatrix = ({ degrees, originXPx, originYPx, scaleX, scaleY }) => {
|
|
61
|
+
const radians = degrees * Math.PI / 180;
|
|
62
|
+
const cos = Math.cos(radians);
|
|
63
|
+
const sin = Math.sin(radians);
|
|
64
|
+
const horizontalScale = scaleX ?? 1;
|
|
65
|
+
const verticalScale = scaleY ?? 1;
|
|
66
|
+
const a = cos * horizontalScale;
|
|
67
|
+
const b = sin * horizontalScale;
|
|
68
|
+
const c = -sin * verticalScale;
|
|
69
|
+
const d = cos * verticalScale;
|
|
70
|
+
return [
|
|
71
|
+
a,
|
|
72
|
+
b,
|
|
73
|
+
c,
|
|
74
|
+
d,
|
|
75
|
+
originXPx - originXPx * a - originYPx * c,
|
|
76
|
+
originYPx - originXPx * b - originYPx * d
|
|
77
|
+
];
|
|
78
|
+
};
|
|
56
79
|
//#endregion
|
|
57
|
-
export { POINTS_PER_PIXEL, applyMatrix, basePageMatrix, displayPointToPdf, pxToPt, rotationMatrix };
|
|
80
|
+
export { POINTS_PER_PIXEL, applyMatrix, basePageMatrix, displayPointToPdf, pxToPt, rotationMatrix, transformMatrix };
|
package/dist/pdf/paint.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { STROKE_DASH_FACTORS, glyphCellOffsetsPx } from "../display-list/primitives.js";
|
|
2
2
|
import { needsShaping } from "../shaping/placeRun.js";
|
|
3
3
|
import { TEXT_RENDER_MODE, createContentStream } from "./contentStream.js";
|
|
4
|
-
import { basePageMatrix,
|
|
4
|
+
import { basePageMatrix, transformMatrix } from "./pageSpace.js";
|
|
5
5
|
import { Result, TaggedError, panic } from "better-result";
|
|
6
6
|
//#region src/pdf/paint.ts
|
|
7
7
|
/**
|
|
@@ -358,7 +358,7 @@ const paintPrimitive = (context, primitive) => {
|
|
|
358
358
|
return;
|
|
359
359
|
case "rotateGroup":
|
|
360
360
|
context.stream.save();
|
|
361
|
-
context.stream.concat(
|
|
361
|
+
context.stream.concat(transformMatrix(primitive));
|
|
362
362
|
for (const child of primitive.children) paintPrimitive(context, child);
|
|
363
363
|
context.stream.restore();
|
|
364
364
|
return;
|
|
@@ -27,6 +27,8 @@ const TEXT_BOX_AUTO_FIT_VALUES = [
|
|
|
27
27
|
"shape"
|
|
28
28
|
];
|
|
29
29
|
const TEXT_BOX_TEXT_WRAP_VALUES = ["square", "none"];
|
|
30
|
+
/** The complete DrawingML transform subset carried by text boxes. */
|
|
31
|
+
const TEXT_BOX_TRANSFORM_PATTERN = /^(?=rotate|scaleX|scaleY)(?:rotate\(-?\d+(?:\.\d+)?deg\)(?: )?)?(?:scaleX\(-1\)(?: )?)?(?:scaleY\(-1\))?$/u;
|
|
30
32
|
const FIELD_KINDS = ["simple", "complex"];
|
|
31
33
|
const MATH_DISPLAYS = ["inline", "block"];
|
|
32
34
|
const SHAPE_FILL_TYPES = [
|
|
@@ -168,6 +170,7 @@ const readParagraphAttrs = (node) => {
|
|
|
168
170
|
const issues = [];
|
|
169
171
|
expectNodeType(node, "paragraph", issues);
|
|
170
172
|
optionalString(attrs, "paraId", "paragraph.attrs.paraId", issues);
|
|
173
|
+
optionalString(attrs, "_docxParagraphSourceToken", "paragraph.attrs._docxParagraphSourceToken", issues);
|
|
171
174
|
optionalString(attrs, "textId", "paragraph.attrs.textId", issues);
|
|
172
175
|
optionalOneOf(attrs, "alignment", "paragraph.attrs.alignment", issues, PARAGRAPH_ALIGNMENT_VALUES);
|
|
173
176
|
optionalOneOf(attrs, "alignmentFromStyle", "paragraph.attrs.alignmentFromStyle", issues, PARAGRAPH_ALIGNMENT_VALUES);
|
|
@@ -367,7 +370,6 @@ const readTableCellAttrs = (node) => {
|
|
|
367
370
|
optionalRecord(attrs, "_originalFormatting", "tableCell.attrs._originalFormatting", issues);
|
|
368
371
|
optionalTableCellRevision(attrs, issues);
|
|
369
372
|
optionalBoolean(attrs, "_preserveVMergeRestart", "tableCell.attrs._preserveVMergeRestart", issues);
|
|
370
|
-
optionalArray(attrs, "_docxVMergeContinuationCells", "tableCell.attrs._docxVMergeContinuationCells", issues);
|
|
371
373
|
return attrsResult(attrs, issues);
|
|
372
374
|
};
|
|
373
375
|
const expectTableCellAttrs = (node) => expectCachedNodeAttrs(node, tableCellAttrsCache, readTableCellAttrs, "table cell attrs");
|
|
@@ -520,6 +522,7 @@ const readTextBoxAttrs = (node) => {
|
|
|
520
522
|
optionalNumber(attrs, "outlineWidth", "textBox.attrs.outlineWidth", issues);
|
|
521
523
|
optionalString(attrs, "outlineColor", "textBox.attrs.outlineColor", issues);
|
|
522
524
|
optionalOneOf(attrs, "outlineStyle", "textBox.attrs.outlineStyle", issues, OUTLINE_STYLE_ATTR_VALUES);
|
|
525
|
+
optionalTextBoxTransform(attrs, "transform", "textBox.attrs.transform", issues);
|
|
523
526
|
optionalNumber(attrs, "marginTop", "textBox.attrs.marginTop", issues);
|
|
524
527
|
optionalNumber(attrs, "marginBottom", "textBox.attrs.marginBottom", issues);
|
|
525
528
|
optionalNumber(attrs, "marginLeft", "textBox.attrs.marginLeft", issues);
|
|
@@ -905,6 +908,21 @@ const optionalString = (attrs, key, path, issues) => {
|
|
|
905
908
|
message: "Expected a string."
|
|
906
909
|
});
|
|
907
910
|
};
|
|
911
|
+
const optionalTextBoxTransform = (attrs, key, path, issues) => {
|
|
912
|
+
const value = attrs[key];
|
|
913
|
+
if (value === void 0 || value === null) return;
|
|
914
|
+
if (typeof value !== "string") {
|
|
915
|
+
issues.push({
|
|
916
|
+
path,
|
|
917
|
+
message: "Expected a string."
|
|
918
|
+
});
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
if (!TEXT_BOX_TRANSFORM_PATTERN.test(value)) issues.push({
|
|
922
|
+
path,
|
|
923
|
+
message: "Expected DrawingML rotation and/or horizontal or vertical flips."
|
|
924
|
+
});
|
|
925
|
+
};
|
|
908
926
|
const optionalSdtListItems = (attrs, key, path, issues) => {
|
|
909
927
|
const value = attrs[key];
|
|
910
928
|
if (value === void 0 || value === null) return;
|
|
@@ -1236,13 +1254,6 @@ const optionalAutospacingBase = (attrs, path, issues) => {
|
|
|
1236
1254
|
optionalNumber(value, "before", `${path}.before`, issues);
|
|
1237
1255
|
optionalNumber(value, "after", `${path}.after`, issues);
|
|
1238
1256
|
};
|
|
1239
|
-
const optionalArray = (attrs, key, path, issues) => {
|
|
1240
|
-
const value = attrs[key];
|
|
1241
|
-
if (value !== void 0 && value !== null && !Array.isArray(value)) issues.push({
|
|
1242
|
-
path,
|
|
1243
|
-
message: "Expected an array."
|
|
1244
|
-
});
|
|
1245
|
-
};
|
|
1246
1257
|
const optionalBorderMap = (attrs, key, path, issues, sides) => {
|
|
1247
1258
|
const value = attrs[key];
|
|
1248
1259
|
if (value === void 0 || value === null) return;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { joinProseParagraphsWithRightPropertySource } from "../../docx/paragraphPropertySource.js";
|
|
1
2
|
import { appendHeadlessInlineResolution } from "../../internal/headlessRevisionResolution.js";
|
|
2
3
|
import { stateAllowsHeadlessRevisionResolution } from "../../internal/headlessRevisionResolutionGuard.js";
|
|
3
4
|
import { expectParagraphAttrs, expectRunPropertyChangeMarkAttrs } from "../attrs/index.js";
|
|
@@ -232,15 +233,23 @@ function resolveChange(from, to, mode, revisionIds, execution = "legacy") {
|
|
|
232
233
|
tr.setNodeAttribute(mappedPos, "pPrMark", null);
|
|
233
234
|
continue;
|
|
234
235
|
}
|
|
236
|
+
const emptyFirstParagraph = holdsNoContent(paragraph);
|
|
235
237
|
const joinedAttrs = {
|
|
236
|
-
...(
|
|
238
|
+
...(emptyFirstParagraph ? nextNode : paragraph).attrs,
|
|
237
239
|
pPrMark: nextNode.attrs["pPrMark"],
|
|
238
240
|
sectionBreakType: nextNode.attrs["sectionBreakType"],
|
|
239
241
|
_sectionProperties: nextNode.attrs["_sectionProperties"]
|
|
240
242
|
};
|
|
241
243
|
try {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
if (emptyFirstParagraph) joinProseParagraphsWithRightPropertySource({
|
|
245
|
+
attrs: joinedAttrs,
|
|
246
|
+
pos: joinPos,
|
|
247
|
+
transaction: tr
|
|
248
|
+
});
|
|
249
|
+
else {
|
|
250
|
+
tr.join(joinPos);
|
|
251
|
+
tr.setNodeMarkup(mappedPos, void 0, joinedAttrs);
|
|
252
|
+
}
|
|
244
253
|
if (ownsSectionEndpoint(paragraph)) {
|
|
245
254
|
removedSectionEndpointCount++;
|
|
246
255
|
removedSectionReferences.push(...sectionReferencesOf(paragraph));
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { decodeTableCellParagraphSourcePayload, restoreTableCellsWithParagraphPropertySources, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
1
2
|
import { standaloneTableCellFromProseMirror } from "../conversion/fromProseDoc.js";
|
|
2
3
|
import { standaloneTableCellToProseMirror } from "../conversion/toProseDoc.js";
|
|
3
4
|
import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
|
|
4
5
|
import { Result } from "better-result";
|
|
5
6
|
import { TableMap } from "prosemirror-tables";
|
|
6
7
|
//#region src/prosemirror/commands/tableCellMergeResolution.ts
|
|
8
|
+
const tableCellContinuationPayload = (node) => {
|
|
9
|
+
const value = node.attrs["_docxVMergeContinuationCells"];
|
|
10
|
+
return value === void 0 || value === null ? null : decodeTableCellParagraphSourcePayload(value);
|
|
11
|
+
};
|
|
7
12
|
const hasMatchingCollapsedTableCellMerge = (node, revisionSet) => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
return continuationCells.some((cell) => {
|
|
13
|
+
const payload = tableCellContinuationPayload(node);
|
|
14
|
+
return payload !== null && payload.cells.some((cell) => {
|
|
11
15
|
const change = getTableCellMergeChange(cell);
|
|
12
16
|
return change !== null && (revisionSet === null || revisionSet.has(change.info.id));
|
|
13
17
|
});
|
|
@@ -71,19 +75,19 @@ const mergeTableCellWithCellAbove = (tr, cellPos) => {
|
|
|
71
75
|
if (!aboveCell || typeof aboveRowspan !== "number" || typeof cellRowspan !== "number" || aboveRowspan < 1 || cellRowspan < 1) return false;
|
|
72
76
|
const continuationCells = tableCellContinuationCells(aboveCell, aboveRowspan);
|
|
73
77
|
continuationCells.push(tableCellContinuationFromNode(cell));
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
78
|
+
const nestedPayload = tableCellContinuationPayload(cell);
|
|
79
|
+
if (nestedPayload) continuationCells.push(...nestedPayload.cells);
|
|
76
80
|
tr.delete(cellPos, cellPos + cell.nodeSize);
|
|
77
81
|
tr.setNodeMarkup(abovePos, void 0, {
|
|
78
82
|
...aboveCell.attrs,
|
|
79
83
|
rowspan: aboveRowspan + cellRowspan,
|
|
80
|
-
_docxVMergeContinuationCells: continuationCells
|
|
84
|
+
_docxVMergeContinuationCells: transportTableCellsWithParagraphPropertySources(continuationCells)
|
|
81
85
|
});
|
|
82
86
|
return true;
|
|
83
87
|
};
|
|
84
88
|
const tableCellContinuationCells = (cell, rowspan) => {
|
|
85
|
-
const
|
|
86
|
-
const cells =
|
|
89
|
+
const payload = tableCellContinuationPayload(cell);
|
|
90
|
+
const cells = payload ? [...payload.cells] : [];
|
|
87
91
|
while (cells.length < rowspan - 1) cells.push(emptyVerticalMergeContinuation());
|
|
88
92
|
return cells;
|
|
89
93
|
};
|
|
@@ -109,8 +113,10 @@ const emptyVerticalMergeContinuation = () => ({
|
|
|
109
113
|
});
|
|
110
114
|
const resolveCollapsedTableCellMerge = (tr, cellPos, mode, revisionSet) => {
|
|
111
115
|
const cell = tr.doc.nodeAt(cellPos);
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
if (!cell) return false;
|
|
117
|
+
const payload = tableCellContinuationPayload(cell);
|
|
118
|
+
if (!payload) return false;
|
|
119
|
+
const stored = payload.cells;
|
|
114
120
|
const matchingIndices = [];
|
|
115
121
|
const nextCells = stored.map((continuationCell, index) => {
|
|
116
122
|
const change = getTableCellMergeChange(continuationCell);
|
|
@@ -142,8 +148,9 @@ const resolveCollapsedTableCellMerge = (tr, cellPos, mode, revisionSet) => {
|
|
|
142
148
|
const rowspan = cell.attrs["rowspan"];
|
|
143
149
|
if (typeof rowspan !== "number" || rowspan !== stored.length + 1 || rectangle.bottom - rectangle.top !== rowspan) return false;
|
|
144
150
|
const restorations = [];
|
|
151
|
+
const restoredCells = restoreTableCellsWithParagraphPropertySources(payload);
|
|
145
152
|
for (const index of splitIndices) {
|
|
146
|
-
const source =
|
|
153
|
+
const source = restoredCells[index];
|
|
147
154
|
if (!source) return false;
|
|
148
155
|
const restoredCell = createRestoredTableCell(cell, source);
|
|
149
156
|
if (!restoredCell) return false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { numPrEqual } from "../../docx/numberingParser.js";
|
|
2
|
-
import { copyParagraphPropertySource, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceTransferId, linkParagraphPropertySourceCandidate, recreateProseNodeWithParagraphPropertySource } from "../../docx/paragraphPropertySource.js";
|
|
2
|
+
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
|
|
3
3
|
import { visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
|
|
4
4
|
import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
|
|
5
5
|
import { DATE_UTC_ATTRIBUTE } from "../../docx/trackedChangeInfo.js";
|
|
@@ -103,23 +103,84 @@ const uniqueParagraphsById = (content, includeTransferIds = false) => {
|
|
|
103
103
|
});
|
|
104
104
|
return paragraphs;
|
|
105
105
|
};
|
|
106
|
+
const restoreParagraphPropertySource = (paragraph, baseParagraph) => {
|
|
107
|
+
copyParagraphPropertySource(paragraph, baseParagraph);
|
|
108
|
+
const baseFormatting = baseParagraph.formatting;
|
|
109
|
+
if (!baseFormatting?.numPr || !baseFormatting.numPrFromStyle || !numPrEqual(baseFormatting.numPr, baseFormatting.numPrFromStyle)) return;
|
|
110
|
+
const { numPr, numPrFromStyle, ...authoredFormatting } = baseFormatting;
|
|
111
|
+
if (canonicalJson(paragraph.formatting ?? {}) !== canonicalJson(authoredFormatting)) return;
|
|
112
|
+
paragraph.formatting = {
|
|
113
|
+
...paragraph.formatting,
|
|
114
|
+
numPr,
|
|
115
|
+
numPrFromStyle
|
|
116
|
+
};
|
|
117
|
+
};
|
|
106
118
|
const restoreParagraphPropertySources = (content, baseContent, linkedTargets, linkedSources) => {
|
|
107
119
|
const baseParagraphs = uniqueParagraphsById(baseContent, true);
|
|
108
120
|
for (const [paraId, paragraph] of uniqueParagraphsById(content)) {
|
|
109
121
|
const baseParagraph = baseParagraphs.get(paraId);
|
|
110
122
|
if (!paragraph || !baseParagraph || linkedTargets.has(paragraph) || linkedSources.has(baseParagraph) || !getParagraphPropertySource(baseParagraph)) continue;
|
|
111
|
-
|
|
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
|
-
};
|
|
123
|
+
restoreParagraphPropertySource(paragraph, baseParagraph);
|
|
121
124
|
}
|
|
122
125
|
};
|
|
126
|
+
const sourceValidationError = (code, message) => new ParagraphPropertySourceValidationError({
|
|
127
|
+
code,
|
|
128
|
+
message
|
|
129
|
+
});
|
|
130
|
+
const validateParagraphPropertySourceTokens = (pmDoc, baseDocument, contract) => {
|
|
131
|
+
const sourceParagraphs = copyDocumentParagraphPropertySources(baseDocument);
|
|
132
|
+
if (!sourceParagraphs) panic("A paragraph-property source contract lost its source registry");
|
|
133
|
+
const currentTokens = /* @__PURE__ */ new Set();
|
|
134
|
+
visitDocumentStoryParagraphs(baseDocument.package.document.content, (paragraph) => {
|
|
135
|
+
const token = getParagraphPropertySourceToken(paragraph);
|
|
136
|
+
if (!token) {
|
|
137
|
+
if (paragraphPropertySourceBelongsToDocument(paragraph, baseDocument)) throw sourceValidationError("invalid_token", "A source-bound paragraph is missing its paragraph-property token.");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (!paragraphPropertySourceTokenMatchesContract(token, contract)) throw sourceValidationError("invalid_token", "The source document contains an invalid paragraph-property token.");
|
|
141
|
+
if (!sourceParagraphs.has(token)) throw sourceValidationError("unknown_token", "The source document contains an unknown paragraph-property token.");
|
|
142
|
+
if (currentTokens.has(token)) throw sourceValidationError("duplicate_token", "The source document contains a duplicate paragraph-property token.");
|
|
143
|
+
currentTokens.add(token);
|
|
144
|
+
});
|
|
145
|
+
const seen = /* @__PURE__ */ new Set();
|
|
146
|
+
const validateToken = (token) => {
|
|
147
|
+
if (token === null || token === void 0) return;
|
|
148
|
+
if (!isParagraphPropertySourceToken(token)) throw sourceValidationError("invalid_token", "A paragraph contains a malformed paragraph-property token.");
|
|
149
|
+
if (!paragraphPropertySourceTokenMatchesContract(token, contract)) throw sourceValidationError("unknown_token", "A paragraph-property token belongs to a different source document.");
|
|
150
|
+
if (seen.has(token)) throw sourceValidationError("duplicate_token", "A paragraph-property token is attached to more than one paragraph.");
|
|
151
|
+
if (!sourceParagraphs.has(token)) throw sourceValidationError("unknown_token", "A paragraph-property token is not present in the source document.");
|
|
152
|
+
seen.add(token);
|
|
153
|
+
};
|
|
154
|
+
const validateTableCellBinding = (binding) => {
|
|
155
|
+
switch (binding.type) {
|
|
156
|
+
case "authored": return;
|
|
157
|
+
case "source":
|
|
158
|
+
validateToken(binding.token);
|
|
159
|
+
return;
|
|
160
|
+
default: return binding;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
pmDoc.descendants((node) => {
|
|
164
|
+
if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
|
|
165
|
+
const continuationCells = expectTableCellAttrs(node)._docxVMergeContinuationCells;
|
|
166
|
+
if (continuationCells !== void 0 && continuationCells !== null) visitTableCellParagraphPropertySourceBindings(decodeTableCellParagraphSourcePayload(continuationCells), (binding) => validateTableCellBinding(binding));
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
if (node.type.name !== "paragraph") return true;
|
|
170
|
+
validateToken(getProseParagraphPropertySourceToken(node));
|
|
171
|
+
return false;
|
|
172
|
+
});
|
|
173
|
+
return sourceParagraphs;
|
|
174
|
+
};
|
|
175
|
+
const restoreParagraphPropertySourcesByToken = (content, baseParagraphs) => {
|
|
176
|
+
visitDocumentStoryParagraphs(content, (paragraph) => {
|
|
177
|
+
const token = getParagraphPropertySourceToken(paragraph);
|
|
178
|
+
if (!token) return;
|
|
179
|
+
const baseParagraph = baseParagraphs.get(token);
|
|
180
|
+
if (!baseParagraph) panic("Validated paragraph-property token lost its source owner");
|
|
181
|
+
restoreParagraphPropertySource(paragraph, baseParagraph);
|
|
182
|
+
});
|
|
183
|
+
};
|
|
123
184
|
const restoreLinkedParagraphPropertySources = (content) => {
|
|
124
185
|
const targetsBySource = /* @__PURE__ */ new Map();
|
|
125
186
|
const linkedTargets = /* @__PURE__ */ new Set();
|
|
@@ -133,7 +194,7 @@ const restoreLinkedParagraphPropertySources = (content) => {
|
|
|
133
194
|
});
|
|
134
195
|
for (const [source, targets] of targetsBySource) if (targets.length === 1) {
|
|
135
196
|
const target = targets.at(0);
|
|
136
|
-
if (target)
|
|
197
|
+
if (target) copyParagraphPropertyCapture(target, source);
|
|
137
198
|
}
|
|
138
199
|
return {
|
|
139
200
|
targets: linkedTargets,
|
|
@@ -143,20 +204,30 @@ const restoreLinkedParagraphPropertySources = (content) => {
|
|
|
143
204
|
/** Convert a ProseMirror document to the document model. */
|
|
144
205
|
function fromProseDoc(pmDoc, baseDocument) {
|
|
145
206
|
assertValidProseMirrorDocument(pmDoc, "Cannot convert invalid ProseMirror document to DOCX model");
|
|
207
|
+
const baseContract = baseDocument ? getDocumentParagraphPropertySourceContract(baseDocument) : void 0;
|
|
208
|
+
const proseContractAttribute = pmDoc.attrs[PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR];
|
|
209
|
+
const proseContract = getProseDocumentParagraphPropertySourceContract(pmDoc);
|
|
210
|
+
if (proseContractAttribute !== null && proseContractAttribute !== void 0 && proseContract === null || (baseContract ?? null) !== proseContract) throw sourceValidationError("contract_mismatch", "The ProseMirror document does not match its paragraph-property source document.");
|
|
211
|
+
const tokenSources = baseContract && proseContract && baseDocument ? validateParagraphPropertySourceTokens(pmDoc, baseDocument, baseContract) : null;
|
|
146
212
|
const blocks = extractBlocks(pmDoc, "resolve", baseDocument?.package.styles ? createStyleEngine(baseDocument.package.styles) : null);
|
|
147
213
|
const linkedSources = restoreLinkedParagraphPropertySources(blocks);
|
|
148
|
-
if (
|
|
214
|
+
if (tokenSources) restoreParagraphPropertySourcesByToken(blocks, tokenSources);
|
|
215
|
+
else if (baseDocument) restoreParagraphPropertySources(blocks, baseDocument.package.document.content, linkedSources.targets, linkedSources.sources);
|
|
149
216
|
const documentBody = { content: blocks };
|
|
150
217
|
if (baseDocument?.package.document.finalSectionProperties) documentBody.finalSectionProperties = baseDocument.package.document.finalSectionProperties;
|
|
151
218
|
if (baseDocument?.package.document.sections) documentBody.sections = baseDocument.package.document.sections;
|
|
152
219
|
if (baseDocument?.package.document.comments) documentBody.comments = baseDocument.package.document.comments;
|
|
153
|
-
if (baseDocument)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
220
|
+
if (baseDocument) {
|
|
221
|
+
const updatedDocument = {
|
|
222
|
+
...baseDocument,
|
|
223
|
+
package: {
|
|
224
|
+
...baseDocument.package,
|
|
225
|
+
document: documentBody
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
copyDocumentParagraphPropertySourceContract(updatedDocument, baseDocument);
|
|
229
|
+
return updatedDocument;
|
|
230
|
+
}
|
|
160
231
|
return { package: { document: documentBody } };
|
|
161
232
|
}
|
|
162
233
|
const isSuggestedMark = (mark) => mark.attrs["provenance"] === "suggested";
|
|
@@ -2606,7 +2677,7 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges, styleReso
|
|
|
2606
2677
|
const colspan = Math.max(cellAttrs.colspan, 1);
|
|
2607
2678
|
cells.push(convertPMTableCell(cellNode, documentCounts, styleResolver));
|
|
2608
2679
|
if (cellAttrs.rowspan > 1) {
|
|
2609
|
-
const continuationCells = cellAttrs._docxVMergeContinuationCells;
|
|
2680
|
+
const continuationCells = cellAttrs._docxVMergeContinuationCells !== void 0 && cellAttrs._docxVMergeContinuationCells !== null ? restoreTableCellsWithParagraphPropertySources(decodeTableCellParagraphSourcePayload(cellAttrs._docxVMergeContinuationCells)) : void 0;
|
|
2610
2681
|
activeVerticalMerges?.set(gridColumn, {
|
|
2611
2682
|
remainingRows: cellAttrs.rowspan - 1,
|
|
2612
2683
|
colspan,
|
|
@@ -2829,6 +2900,8 @@ function convertPMTextBox(node, styleResolver = null) {
|
|
|
2829
2900
|
}
|
|
2830
2901
|
};
|
|
2831
2902
|
if (attrs.textBoxId) shape.id = attrs.textBoxId;
|
|
2903
|
+
const transform = parseTransformAttr(attrs.transform);
|
|
2904
|
+
if (transform) shape.transform = transform;
|
|
2832
2905
|
if (attrs.fillColor) shape.fill = {
|
|
2833
2906
|
type: "solid",
|
|
2834
2907
|
color: { rgb: attrs.fillColor.replace("#", "") }
|