@stll/folio-core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ai-edits/headless.d.ts +2 -1
- package/dist/ai-edits/headless.js +9 -7
- package/dist/compat/eigenpal.d.ts +29 -0
- package/dist/compat/eigenpal.js +24 -0
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +22 -0
- package/dist/controller/layoutSession.d.ts +1 -1
- package/dist/docx/encryption/agileDecryption.d.ts +6 -0
- package/dist/docx/encryption/agileDecryption.js +208 -0
- package/dist/docx/encryption/compoundFile.d.ts +20 -0
- package/dist/docx/encryption/compoundFile.js +249 -0
- package/dist/docx/encryption/containerFormat.d.ts +15 -0
- package/dist/docx/encryption/containerFormat.js +40 -0
- package/dist/docx/encryption/cryptoBytes.d.ts +11 -0
- package/dist/docx/encryption/cryptoBytes.js +55 -0
- package/dist/docx/encryption/encryptionInfo.d.ts +32 -0
- package/dist/docx/encryption/encryptionInfo.js +128 -0
- package/dist/docx/encryption/errors.d.ts +18 -0
- package/dist/docx/encryption/errors.js +13 -0
- package/dist/docx/encryption/index.d.ts +4 -0
- package/dist/docx/encryption/index.js +4 -0
- package/dist/docx/encryption/openEncryptedDocx.d.ts +28 -0
- package/dist/docx/encryption/openEncryptedDocx.js +65 -0
- package/dist/docx/index.d.ts +3 -1
- package/dist/docx/index.js +3 -1
- package/dist/docx/parser.d.ts +4 -5
- package/dist/docx/parser.js +8 -2
- package/dist/docx/unzip.d.ts +7 -5
- package/dist/docx/unzip.js +8 -2
- package/dist/index.d.ts +6 -5
- package/dist/index.js +2 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -1
- package/dist/layout-bridge/convert/headerFooterLayout.js +16 -6
- package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +1 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
- package/dist/layout-engine/index.js +27 -1
- package/dist/layout-engine/measure/measureBlocks.js +15 -1
- package/dist/layout-engine/measure/measureParagraph.js +37 -6
- package/dist/layout-engine/types.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +2 -1
- package/dist/layout-painter/renderParagraph.js +30 -5
- package/dist/layout-painter/renderTable.js +17 -0
- package/dist/managers/DocumentLoaderManager.d.ts +3 -1
- package/dist/managers/DocumentLoaderManager.js +3 -2
- package/dist/paged-layout/headerFooterMargins.d.ts +3 -1
- package/dist/paged-layout/headerFooterMargins.js +5 -3
- package/dist/prosemirror/attrs/index.js +1 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +7 -2
- package/dist/prosemirror/conversion/toProseDoc.js +14 -7
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +4 -2
- package/dist/server.d.ts +2 -2
- package/dist/utils/fontResolver.d.ts +3 -1
- package/dist/utils/fontResolver.js +28 -4
- package/package.json +9 -1
|
@@ -16,13 +16,13 @@ function hasAuthoredVisualContent(block) {
|
|
|
16
16
|
if (attrs.spacingExplicit?.before || attrs.spacingExplicit?.after) return true;
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
|
-
function normalizeHeaderFooterMeasureBlocks(blocks) {
|
|
20
|
-
return normalizeFlowBlockArray(blocks);
|
|
19
|
+
function normalizeHeaderFooterMeasureBlocks(blocks, section = "header") {
|
|
20
|
+
return normalizeFlowBlockArray(blocks, { suppressTrailingEmptyAfterTable: section === "header" });
|
|
21
21
|
}
|
|
22
|
-
function normalizeFlowBlockArray(blocks) {
|
|
22
|
+
function normalizeFlowBlockArray(blocks, normalization) {
|
|
23
23
|
const trailingEmptyAfterTable = /* @__PURE__ */ new Set();
|
|
24
24
|
const lastIndex = blocks.length - 1;
|
|
25
|
-
if (lastIndex > 0) {
|
|
25
|
+
if (normalization.suppressTrailingEmptyAfterTable && lastIndex > 0) {
|
|
26
26
|
const cur = blocks[lastIndex];
|
|
27
27
|
if (blocks[lastIndex - 1]?.kind === "table" && cur?.kind === "paragraph" && cur.runs.length === 0 && !hasAuthoredVisualContent(cur)) trailingEmptyAfterTable.add(lastIndex);
|
|
28
28
|
}
|
|
@@ -70,12 +70,21 @@ function normalizeFlowBlockArray(blocks) {
|
|
|
70
70
|
};
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
+
function isCanonicalTrailingEmptyParagraphAfterTable(blocks, index) {
|
|
74
|
+
const cur = blocks[index];
|
|
75
|
+
const prev = blocks[index - 1];
|
|
76
|
+
return index === blocks.length - 1 && prev?.kind === "table" && cur?.kind === "paragraph" && isVisuallyEmptyParagraph(cur) && !hasAuthoredVisualContent(cur);
|
|
77
|
+
}
|
|
78
|
+
function isVisuallyEmptyParagraph(block) {
|
|
79
|
+
if (block.kind !== "paragraph") return false;
|
|
80
|
+
return block.runs.every((run) => run.kind === "text" && run.text.trim().length === 0);
|
|
81
|
+
}
|
|
73
82
|
function normalizeTableBlock(block) {
|
|
74
83
|
const blockState = { changed: false };
|
|
75
84
|
const rows = block.rows.map((row) => {
|
|
76
85
|
const rowState = { changed: false };
|
|
77
86
|
const cells = row.cells.map((cell) => {
|
|
78
|
-
const normalizedBlocks = normalizeFlowBlockArray(cell.blocks);
|
|
87
|
+
const normalizedBlocks = normalizeFlowBlockArray(cell.blocks, { suppressTrailingEmptyAfterTable: true });
|
|
79
88
|
if (!normalizedBlocks.some((normalizedBlock, idx) => normalizedBlock !== cell.blocks[idx])) return cell;
|
|
80
89
|
rowState.changed = true;
|
|
81
90
|
return {
|
|
@@ -232,6 +241,7 @@ function calculateHeaderFooterMarginPushBounds(blocks, measures, flowHeight, met
|
|
|
232
241
|
const block = blocks[i];
|
|
233
242
|
const measure = measures[i];
|
|
234
243
|
if (!block || !measure) continue;
|
|
244
|
+
if (isCanonicalTrailingEmptyParagraphAfterTable(blocks, i)) continue;
|
|
235
245
|
if (block.kind === "paragraph" && measure.kind === "paragraph") {
|
|
236
246
|
const paragraphBottomY = cursorY + measure.totalHeight;
|
|
237
247
|
top = Math.min(top, cursorY);
|
|
@@ -312,7 +322,7 @@ function convertHeaderFooterPmDocToContent(pmDoc, contentWidth, metrics, options
|
|
|
312
322
|
}
|
|
313
323
|
function finalizeHeaderFooterContent(blocks, contentWidth, metrics, options) {
|
|
314
324
|
if (blocks.length === 0) return;
|
|
315
|
-
const blocksForMeasure = normalizeHeaderFooterMeasureBlocks(blocks);
|
|
325
|
+
const blocksForMeasure = normalizeHeaderFooterMeasureBlocks(blocks, metrics.section);
|
|
316
326
|
const measures = options.measureBlocks(blocksForMeasure, contentWidth);
|
|
317
327
|
let flowHeight = 0;
|
|
318
328
|
for (let i = 0; i < measures.length; i++) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FlowBlock } from "../../layout-engine/types.js";
|
|
2
1
|
import { TemplatePreviewValue } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
2
|
+
import { FlowBlock } from "../../layout-engine/types.js";
|
|
3
3
|
|
|
4
4
|
//#region src/layout-bridge/convert/templatePreviewFlow.d.ts
|
|
5
5
|
/** One marker→value substitution, in PM doc positions. */
|
|
@@ -732,6 +732,7 @@ function convertParagraphAttrs(pmAttrs, theme, listCounters, listAbstractCounter
|
|
|
732
732
|
if (pmAttrs.pageBreakBefore) attrs.pageBreakBefore = true;
|
|
733
733
|
if (pmAttrs.keepNext) attrs.keepNext = true;
|
|
734
734
|
if (pmAttrs.keepLines) attrs.keepLines = true;
|
|
735
|
+
if (pmAttrs.widowControl === false) attrs.widowControl = false;
|
|
735
736
|
if (pmAttrs.contextualSpacing) attrs.contextualSpacing = true;
|
|
736
737
|
if (pmAttrs.runInWithNext) attrs.runInWithNext = true;
|
|
737
738
|
if (directionIsRtl(pmAttrs.direction)) attrs.bidi = true;
|
|
@@ -941,6 +942,7 @@ function convertTableRow(node, startPos, options, tableCellMargins) {
|
|
|
941
942
|
if (attrs.height) row.height = twipsToPixels(attrs.height);
|
|
942
943
|
if (attrs.heightRule) row.heightRule = attrs.heightRule;
|
|
943
944
|
if (attrs.isHeader) row.isHeader = attrs.isHeader;
|
|
945
|
+
if (attrs.hidden) row.hidden = attrs.hidden;
|
|
944
946
|
return row;
|
|
945
947
|
}
|
|
946
948
|
/**
|
|
@@ -72,6 +72,9 @@ function getSpacingAfter(block) {
|
|
|
72
72
|
if (isEmptyParagraph(block) && !block.attrs?.spacingExplicit?.after) return 0;
|
|
73
73
|
return value;
|
|
74
74
|
}
|
|
75
|
+
function hasWidowControl(block) {
|
|
76
|
+
return block.attrs?.widowControl !== false;
|
|
77
|
+
}
|
|
75
78
|
/**
|
|
76
79
|
* Apply contextual spacing suppression (OOXML §17.3.1.9).
|
|
77
80
|
*
|
|
@@ -309,6 +312,28 @@ function layoutParagraph(block, measure, paginator, contentWidth, footnoteHeight
|
|
|
309
312
|
fittingLines++;
|
|
310
313
|
} else break;
|
|
311
314
|
}
|
|
315
|
+
let forceBreakAfterFragment = false;
|
|
316
|
+
if (hasWidowControl(block)) {
|
|
317
|
+
const remainingAfter = lines.length - (currentLineIndex + fittingLines);
|
|
318
|
+
if (fittingLines > 1 && remainingAfter === 1) {
|
|
319
|
+
if (currentLineIndex === 0 && fittingLines === 2 && state.cursorY !== state.topMargin) {
|
|
320
|
+
paginator.forceColumnBreak();
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
fittingLines -= 1;
|
|
324
|
+
forceBreakAfterFragment = true;
|
|
325
|
+
linesHeight = 0;
|
|
326
|
+
linesFnHeight = 0;
|
|
327
|
+
linesFnIds.length = 0;
|
|
328
|
+
for (let j = currentLineIndex; j < currentLineIndex + fittingLines; j++) {
|
|
329
|
+
const line = lines[j];
|
|
330
|
+
linesHeight += measuredLineAdvance(line);
|
|
331
|
+
const lineRefs = getLineFootnoteRefs(block, line.fromRun, line.toRun, footnoteHeightById);
|
|
332
|
+
linesFnHeight += lineRefs.height;
|
|
333
|
+
for (const id of lineRefs.ids) linesFnIds.push(id);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
312
337
|
const isFirstFragment = currentLineIndex === 0;
|
|
313
338
|
const isLastFragment = currentLineIndex + fittingLines >= lines.length;
|
|
314
339
|
const effectiveSpaceBefore = isFirstFragment ? spaceBefore : 0;
|
|
@@ -336,7 +361,8 @@ function layoutParagraph(block, measure, paginator, contentWidth, footnoteHeight
|
|
|
336
361
|
fragment.y = paginator.addFragment(fragment, linesHeight, effectiveSpaceBefore, effectiveSpaceAfter).y;
|
|
337
362
|
if (linesFnHeight > 0) paginator.addFootnoteHeight(linesFnHeight, linesFnIds);
|
|
338
363
|
currentLineIndex += fittingLines;
|
|
339
|
-
if (currentLineIndex < lines.length) paginator.
|
|
364
|
+
if (currentLineIndex < lines.length) if (forceBreakAfterFragment) paginator.forceColumnBreak();
|
|
365
|
+
else paginator.ensureFits(measuredLineAdvance(lines[currentLineIndex]));
|
|
340
366
|
}
|
|
341
367
|
}
|
|
342
368
|
/**
|
|
@@ -71,6 +71,11 @@ function measureTableCellBlockVisualHeight(block, blockMeasure) {
|
|
|
71
71
|
}
|
|
72
72
|
let maxImageHeight = 0;
|
|
73
73
|
for (const run of inlineImageRuns) maxImageHeight = Math.max(maxImageHeight, run.height);
|
|
74
|
+
if (inlineImageRuns.length === 1) {
|
|
75
|
+
const spacingBefore = paragraphBlock.attrs?.spacing?.before ?? 0;
|
|
76
|
+
const spacingAfter = paragraphBlock.attrs?.spacing?.after ?? 0;
|
|
77
|
+
return spacingBefore + maxImageHeight + spacingAfter;
|
|
78
|
+
}
|
|
74
79
|
const spacingBefore = paragraphBlock.attrs?.spacing?.before ?? 0;
|
|
75
80
|
const spacingAfter = paragraphBlock.attrs?.spacing?.after ?? 0;
|
|
76
81
|
return spacingBefore + maxImageHeight + spacingAfter;
|
|
@@ -143,6 +148,16 @@ function measureTableBlock(tableBlock, contentWidth, fieldValues) {
|
|
|
143
148
|
});
|
|
144
149
|
for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
|
|
145
150
|
const row = rows[rowIdx];
|
|
151
|
+
const sourceRow = tableBlock.rows[rowIdx];
|
|
152
|
+
if (sourceRow?.hidden) {
|
|
153
|
+
row.height = 0;
|
|
154
|
+
row.cells = sourceRow.cells.map(() => ({
|
|
155
|
+
blocks: [],
|
|
156
|
+
width: 0,
|
|
157
|
+
height: 0
|
|
158
|
+
}));
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
146
161
|
const sourceRowCells = tableBlock.rows[rowIdx]?.cells;
|
|
147
162
|
let maxCellHeightWithBorders = 0;
|
|
148
163
|
for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
|
|
@@ -160,7 +175,6 @@ function measureTableBlock(tableBlock, contentWidth, fieldValues) {
|
|
|
160
175
|
cell.height += padTop + padBottom;
|
|
161
176
|
maxCellHeightWithBorders = Math.max(maxCellHeightWithBorders, cell.height + getTableCellVerticalBorderHeight(sourceCell));
|
|
162
177
|
}
|
|
163
|
-
const sourceRow = tableBlock.rows[rowIdx];
|
|
164
178
|
const explicitHeight = sourceRow?.height;
|
|
165
179
|
const heightRule = sourceRow?.heightRule;
|
|
166
180
|
if (explicitHeight && heightRule === "exact") row.height = explicitHeight;
|
|
@@ -21,6 +21,10 @@ const DEFAULT_FONT_SIZE = 11;
|
|
|
21
21
|
const DEFAULT_FONT_FAMILY = "Calibri";
|
|
22
22
|
const DEFAULT_LINE_HEIGHT_MULTIPLIER = 1;
|
|
23
23
|
const WIDTH_TOLERANCE = .5;
|
|
24
|
+
const JUSTIFY_SHRINK_TOLERANCE_RATIO = .016;
|
|
25
|
+
const JUSTIFY_PROSE_SHRINK_TOLERANCE_RATIO = .025;
|
|
26
|
+
const JUSTIFY_HANGING_TAB_SHRINK_TOLERANCE_RATIO = .021;
|
|
27
|
+
const ALL_CAPS_RATIO_THRESHOLD = .8;
|
|
24
28
|
/**
|
|
25
29
|
* Find the longest prefix of `text` that fits within `maxWidth` pixels.
|
|
26
30
|
* Returns the number of characters that fit (at least 1 if `forceMin` is true).
|
|
@@ -266,6 +270,10 @@ function hasFollowingTabOnLine(runs, tabIndex) {
|
|
|
266
270
|
}
|
|
267
271
|
return false;
|
|
268
272
|
}
|
|
273
|
+
function canClampTabToRightEdge(alignment, currentLineWidth) {
|
|
274
|
+
if (alignment === "start" || alignment === "default") return currentLineWidth > WIDTH_TOLERANCE;
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
269
277
|
/**
|
|
270
278
|
* Width of the inline content preceding the first `.` in the runs that follow
|
|
271
279
|
* a tab, used to anchor `decimal` tab stops. Mirrors `getTextAfterTab` +
|
|
@@ -299,6 +307,25 @@ function measureDecimalPrefixWidthAfterTab(runs, tabIndex, fieldValues) {
|
|
|
299
307
|
function isSpaceOrTab(char) {
|
|
300
308
|
return char === " " || char === " ";
|
|
301
309
|
}
|
|
310
|
+
function uppercaseLetterRatio(text) {
|
|
311
|
+
let letters = 0;
|
|
312
|
+
let uppercase = 0;
|
|
313
|
+
for (const char of text) {
|
|
314
|
+
const lower = char.toLocaleLowerCase();
|
|
315
|
+
const upper = char.toLocaleUpperCase();
|
|
316
|
+
if (lower === upper) continue;
|
|
317
|
+
letters++;
|
|
318
|
+
if (char === upper) uppercase++;
|
|
319
|
+
}
|
|
320
|
+
return letters === 0 ? 0 : uppercase / letters;
|
|
321
|
+
}
|
|
322
|
+
function justifyShrinkToleranceRatio(block) {
|
|
323
|
+
const hasTabStops = (block.attrs?.tabs?.length ?? 0) > 0;
|
|
324
|
+
const hasTabRuns = block.runs.some(isTabRun);
|
|
325
|
+
if (hasTabStops || hasTabRuns) return (block.attrs?.indent?.firstLine ?? 0) === 0 ? JUSTIFY_HANGING_TAB_SHRINK_TOLERANCE_RATIO : JUSTIFY_SHRINK_TOLERANCE_RATIO;
|
|
326
|
+
if (uppercaseLetterRatio(block.runs.map((run) => isTextRun(run) ? run.text ?? "" : "").join("")) > ALL_CAPS_RATIO_THRESHOLD) return JUSTIFY_SHRINK_TOLERANCE_RATIO;
|
|
327
|
+
return JUSTIFY_PROSE_SHRINK_TOLERANCE_RATIO;
|
|
328
|
+
}
|
|
302
329
|
function trimTrailingSpacesAndTabs(text) {
|
|
303
330
|
let end = text.length;
|
|
304
331
|
while (end > 0) {
|
|
@@ -384,6 +411,8 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
384
411
|
const runs = block.runs;
|
|
385
412
|
const attrs = block.attrs;
|
|
386
413
|
const spacing = attrs?.spacing;
|
|
414
|
+
const isJustifiedParagraph = attrs?.alignment === "justify";
|
|
415
|
+
const justifyToleranceRatio = justifyShrinkToleranceRatio(block);
|
|
387
416
|
const floatingZones = options?.floatingZones;
|
|
388
417
|
const paragraphYOffset = options?.paragraphYOffset ?? 0;
|
|
389
418
|
const indent = attrs?.indent;
|
|
@@ -589,15 +618,16 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
589
618
|
const lineX = currentLine.width + currentLine.leftOffset;
|
|
590
619
|
const isFirstLine = lines.length === 0;
|
|
591
620
|
const contentX = indentLeft + (isFirstLine ? firstLineOffset + markerInlineWidth : 0) + lineX;
|
|
592
|
-
|
|
621
|
+
const tabResult = calculateTabWidth(contentX, {
|
|
593
622
|
...attrs?.tabs !== void 0 ? { explicitStops: attrs.tabs } : {},
|
|
594
623
|
leftIndent: pixelsToTwips(indentLeft)
|
|
595
624
|
}, {
|
|
596
625
|
followingWidth,
|
|
597
626
|
decimalPrefixWidth
|
|
598
|
-
})
|
|
627
|
+
});
|
|
628
|
+
let tabWidth = tabResult.width;
|
|
599
629
|
const lineRightEdgeX = indentLeft + (isFirstLine ? firstLineOffset + markerInlineWidth : 0) + currentLine.availableWidth + currentLine.leftOffset;
|
|
600
|
-
if (!hasFollowingTabOnLine(runs, runIndex) && (tabWidth > 0 || followingWidth > 0) && contentX + tabWidth + followingWidth > lineRightEdgeX + WIDTH_TOLERANCE) tabWidth = Math.max(1, lineRightEdgeX - contentX - followingWidth);
|
|
630
|
+
if (!hasFollowingTabOnLine(runs, runIndex) && canClampTabToRightEdge(tabResult.alignment, currentLine.width) && (tabWidth > 0 || followingWidth > 0) && contentX + tabWidth + followingWidth > lineRightEdgeX + WIDTH_TOLERANCE) tabWidth = Math.max(1, lineRightEdgeX - contentX - followingWidth);
|
|
601
631
|
if (currentLine.width + tabWidth > currentLine.availableWidth + WIDTH_TOLERANCE) {
|
|
602
632
|
startNewLine(runIndex, 0);
|
|
603
633
|
updateMaxFont(style);
|
|
@@ -691,7 +721,8 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
691
721
|
}
|
|
692
722
|
const word = text.slice(charIndex, nextBreak);
|
|
693
723
|
const wordWidth = measureTextWidth(word, style);
|
|
694
|
-
|
|
724
|
+
const widthTolerance = isJustifiedParagraph ? Math.max(WIDTH_TOLERANCE, currentLine.availableWidth * justifyToleranceRatio) : WIDTH_TOLERANCE;
|
|
725
|
+
if (wordWidth > currentLine.availableWidth + widthTolerance) {
|
|
695
726
|
let chunkStart = 0;
|
|
696
727
|
while (chunkStart < word.length) {
|
|
697
728
|
const spaceLeft = currentLine.availableWidth - currentLine.width + WIDTH_TOLERANCE;
|
|
@@ -719,8 +750,8 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
719
750
|
continue;
|
|
720
751
|
}
|
|
721
752
|
const rawGlueWidth = nextBreak === text.length && word.length > 0 && !isBreakChar(word[word.length - 1]) ? trailingGlueWidths[runIndex] ?? 0 : 0;
|
|
722
|
-
const glueWidth = rawGlueWidth > 0 && wordWidth + rawGlueWidth <= getPostWrapAvailableWidth() +
|
|
723
|
-
if (currentLine.width > 0 && currentLine.width + wordWidth + glueWidth > currentLine.availableWidth +
|
|
753
|
+
const glueWidth = rawGlueWidth > 0 && wordWidth + rawGlueWidth <= getPostWrapAvailableWidth() + widthTolerance ? rawGlueWidth : 0;
|
|
754
|
+
if (currentLine.width > 0 && currentLine.width + wordWidth + glueWidth > currentLine.availableWidth + widthTolerance) {
|
|
724
755
|
startNewLine(runIndex, charIndex);
|
|
725
756
|
updateMaxFont(lineHeightStyle);
|
|
726
757
|
}
|
|
@@ -303,6 +303,7 @@ type ParagraphAttrs = {
|
|
|
303
303
|
indent?: ParagraphIndent;
|
|
304
304
|
keepNext?: boolean;
|
|
305
305
|
keepLines?: boolean;
|
|
306
|
+
widowControl?: boolean;
|
|
306
307
|
pageBreakBefore?: boolean;
|
|
307
308
|
styleId?: string;
|
|
308
309
|
contextualSpacing?: boolean;
|
|
@@ -432,6 +433,7 @@ type TableRow = {
|
|
|
432
433
|
height?: number;
|
|
433
434
|
heightRule?: "auto" | "atLeast" | "exact";
|
|
434
435
|
isHeader?: boolean;
|
|
436
|
+
hidden?: boolean;
|
|
435
437
|
};
|
|
436
438
|
/**
|
|
437
439
|
* Floating table positioning info (pixel values).
|
|
@@ -518,6 +520,7 @@ type SectionBreakBlock = {
|
|
|
518
520
|
};
|
|
519
521
|
type PageHeaderFooterRefs = {
|
|
520
522
|
titlePg?: boolean;
|
|
523
|
+
evenAndOddHeaders?: boolean;
|
|
521
524
|
headerDefault?: string;
|
|
522
525
|
headerFirst?: string;
|
|
523
526
|
headerEven?: string;
|
|
@@ -1162,7 +1162,8 @@ function applySectionHeaderFooterOptions(page, pageOptions, options) {
|
|
|
1162
1162
|
if (!refs) return false;
|
|
1163
1163
|
const isFirstSectionPage = page.sectionPageNumber === 1;
|
|
1164
1164
|
const useFirst = refs.titlePg === true && isFirstSectionPage;
|
|
1165
|
-
const
|
|
1165
|
+
const sectionPageNumber = page.sectionPageNumber ?? page.number;
|
|
1166
|
+
const useEven = refs.evenAndOddHeaders === true && sectionPageNumber % 2 === 0;
|
|
1166
1167
|
const headerRId = (() => {
|
|
1167
1168
|
if (useFirst) return refs.headerFirst;
|
|
1168
1169
|
if (useEven && refs.headerEven) return refs.headerEven;
|
|
@@ -330,6 +330,10 @@ function renderTabRun(run, doc, width, leader) {
|
|
|
330
330
|
} else span.textContent = "\xA0";
|
|
331
331
|
return span;
|
|
332
332
|
}
|
|
333
|
+
function canClampTabToRightEdge(alignment, hasPriorRenderedContent) {
|
|
334
|
+
if (alignment === "start" || alignment === "default") return hasPriorRenderedContent;
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
333
337
|
function applyTabUnderline(element, run) {
|
|
334
338
|
if (!run.underline) return;
|
|
335
339
|
removeUnderlineTextDecoration(element);
|
|
@@ -529,7 +533,9 @@ const EMPTY_SEQ_VALUES = /* @__PURE__ */ new Map();
|
|
|
529
533
|
* Returns the cached fallback when no render context is available.
|
|
530
534
|
*/
|
|
531
535
|
function resolveFieldText(run, context) {
|
|
532
|
-
|
|
536
|
+
const fallback = run.fallback ?? "";
|
|
537
|
+
if (run.fieldType === "OTHER" && run.pmStart === void 0) return fallback;
|
|
538
|
+
if (!context) return fallback;
|
|
533
539
|
const fieldContext = {
|
|
534
540
|
pageNumber: context.pageNumber,
|
|
535
541
|
totalPages: context.totalPages,
|
|
@@ -540,7 +546,7 @@ function resolveFieldText(run, context) {
|
|
|
540
546
|
...context.sectionPages === void 0 ? {} : { sectionPages: context.sectionPages }
|
|
541
547
|
};
|
|
542
548
|
return evaluateFieldInstruction(run.instruction || run.fieldType, fieldContext, {
|
|
543
|
-
fallback
|
|
549
|
+
fallback,
|
|
544
550
|
...run.pmStart === void 0 ? {} : { instanceId: run.pmStart },
|
|
545
551
|
...run.fldLock ? { locked: true } : {}
|
|
546
552
|
});
|
|
@@ -710,6 +716,17 @@ function splitTextRunsByEastAsia(runs) {
|
|
|
710
716
|
* must trigger within this slack.
|
|
711
717
|
*/
|
|
712
718
|
const RIGHT_EDGE_EPSILON_PX = .5;
|
|
719
|
+
function countShrinkableSpaces(runs) {
|
|
720
|
+
let count = 0;
|
|
721
|
+
for (const run of runs) if (isTextRun(run)) {
|
|
722
|
+
for (const char of run.text ?? "") if (char === " ") count++;
|
|
723
|
+
} else if (isFieldRun(run)) {
|
|
724
|
+
for (const char of run.fallback ?? "") if (char === " ") count++;
|
|
725
|
+
} else if (isMathRun(run)) {
|
|
726
|
+
for (const char of run.plainText ?? "") if (char === " ") count++;
|
|
727
|
+
}
|
|
728
|
+
return count;
|
|
729
|
+
}
|
|
713
730
|
/**
|
|
714
731
|
* Build a TextMeasureStyle from a TextRun or FieldRun's relevant fields.
|
|
715
732
|
*/
|
|
@@ -890,8 +907,16 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
890
907
|
}
|
|
891
908
|
if (alignment === "justify" && options) {
|
|
892
909
|
if (!options.isLastLine || options.paragraphEndsWithLineBreak) {
|
|
893
|
-
|
|
894
|
-
|
|
910
|
+
const overfullPx = line.width - options.availableWidth;
|
|
911
|
+
const shrinkableSpaces = countShrinkableSpaces(runsForLine);
|
|
912
|
+
if (overfullPx > RIGHT_EDGE_EPSILON_PX && shrinkableSpaces > 0) {
|
|
913
|
+
lineEl.style.textAlign = "left";
|
|
914
|
+
lineEl.style.textAlignLast = "auto";
|
|
915
|
+
lineEl.style.wordSpacing = `${-overfullPx / shrinkableSpaces}px`;
|
|
916
|
+
} else {
|
|
917
|
+
lineEl.style.textAlign = "justify";
|
|
918
|
+
lineEl.style.textAlignLast = "justify";
|
|
919
|
+
}
|
|
895
920
|
lineEl.style.width = `${options.availableWidth}px`;
|
|
896
921
|
}
|
|
897
922
|
}
|
|
@@ -967,7 +992,7 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
967
992
|
break;
|
|
968
993
|
}
|
|
969
994
|
let tabWidth = tabResult.width;
|
|
970
|
-
if (lineRightEdgeX !== void 0 && currentX + tabWidth + followingWidthForCheck > lineRightEdgeX) tabWidth = Math.max(1, lineRightEdgeX - currentX - followingWidthForCheck);
|
|
995
|
+
if (lineRightEdgeX !== void 0 && canClampTabToRightEdge(tabResult.alignment, i > 0) && currentX + tabWidth + followingWidthForCheck > lineRightEdgeX) tabWidth = Math.max(1, lineRightEdgeX - currentX - followingWidthForCheck);
|
|
971
996
|
const tabEl = renderTabRun(run, doc, tabWidth, tabResult.leader);
|
|
972
997
|
lineEl.append(tabEl);
|
|
973
998
|
currentX += tabWidth;
|
|
@@ -97,6 +97,10 @@ function renderCellContent(cell, cellMeasure, context, doc) {
|
|
|
97
97
|
};
|
|
98
98
|
const fragEl = renderParagraphFragment(syntheticFragment, paragraphBlock, paragraphMeasure, cellContext, { document: doc });
|
|
99
99
|
fragEl.style.position = "relative";
|
|
100
|
+
fragEl.style.boxSizing = "border-box";
|
|
101
|
+
fragEl.style.height = `${paragraphMeasure.totalHeight}px`;
|
|
102
|
+
const spaceBefore = paragraphBlock.attrs?.spacing?.before ?? 0;
|
|
103
|
+
if (spaceBefore > 0) fragEl.style.paddingTop = `${spaceBefore}px`;
|
|
100
104
|
contentEl.append(fragEl);
|
|
101
105
|
cumulativeY += paragraphMeasure.totalHeight;
|
|
102
106
|
} else if (block?.kind === "table" && measure?.kind === "table") {
|
|
@@ -138,6 +142,10 @@ function renderNestedTable(block, measure, context, doc) {
|
|
|
138
142
|
const row = block.rows[rowIndex];
|
|
139
143
|
const rowMeasure = measure.rows[rowIndex];
|
|
140
144
|
if (!row || !rowMeasure) continue;
|
|
145
|
+
if (row.hidden) {
|
|
146
|
+
y += rowMeasure.height;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
141
149
|
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, void 0, block.bidi);
|
|
142
150
|
tableEl.append(rowEl);
|
|
143
151
|
y += rowMeasure.height;
|
|
@@ -346,6 +354,10 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
346
354
|
const hdrRow = block.rows[hdrIdx];
|
|
347
355
|
const hdrRowMeasure = measure.rows[hdrIdx];
|
|
348
356
|
if (!hdrRow || !hdrRowMeasure) continue;
|
|
357
|
+
if (hdrRow.hidden) {
|
|
358
|
+
y += hdrRowMeasure.height;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
349
361
|
const rowEl = renderTableRow(hdrRow, hdrRowMeasure, hdrIdx, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, hdrIdx === 0, block.bidi);
|
|
350
362
|
rowEl.dataset["repeatedHeader"] = "true";
|
|
351
363
|
tableEl.append(rowEl);
|
|
@@ -369,6 +381,10 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
369
381
|
const row = block.rows[rowIndex];
|
|
370
382
|
const rowMeasure = measure.rows[rowIndex];
|
|
371
383
|
if (!row || !rowMeasure) continue;
|
|
384
|
+
if (row.hidden) {
|
|
385
|
+
y += rowMeasure.height;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
372
388
|
const isFirstRowInFragment = headerRowCount > 0 && fragment.continuesFromPrev ? false : fragment.continuesFromPrev && rowIndex === fragment.fromRow;
|
|
373
389
|
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, isFirstRowInFragment, block.bidi);
|
|
374
390
|
contentParent.append(rowEl);
|
|
@@ -376,6 +392,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
376
392
|
}
|
|
377
393
|
let handleY = 0;
|
|
378
394
|
for (let rowIdx = fragment.fromRow; rowIdx < fragment.toRow; rowIdx++) {
|
|
395
|
+
if (block.rows[rowIdx]?.hidden) continue;
|
|
379
396
|
handleY += measure.rows[rowIdx]?.height ?? 0;
|
|
380
397
|
if (rowIdx < fragment.toRow - 1) {
|
|
381
398
|
const rowHandle = doc.createElement("div");
|
|
@@ -41,7 +41,9 @@ declare class DocumentLoaderManager {
|
|
|
41
41
|
* the result (and any error) when a newer load started while this one was in
|
|
42
42
|
* flight.
|
|
43
43
|
*/
|
|
44
|
-
loadBuffer(buffer: DocxInput
|
|
44
|
+
loadBuffer(buffer: DocxInput, options?: {
|
|
45
|
+
password?: string | undefined;
|
|
46
|
+
}): Promise<void>;
|
|
45
47
|
}
|
|
46
48
|
//#endregion
|
|
47
49
|
export { DocumentLoadState, DocumentLoaderCallbacks, DocumentLoaderHistory, DocumentLoaderManager };
|
|
@@ -43,14 +43,15 @@ var DocumentLoaderManager = class {
|
|
|
43
43
|
* the result (and any error) when a newer load started while this one was in
|
|
44
44
|
* flight.
|
|
45
45
|
*/
|
|
46
|
-
async loadBuffer(buffer) {
|
|
46
|
+
async loadBuffer(buffer, options = {}) {
|
|
47
47
|
const { history, onError, setDocumentLoadState } = this.callbacks;
|
|
48
48
|
const generation = ++this.loadGeneration;
|
|
49
49
|
if (!(history.state !== null)) setDocumentLoadState({ status: "loading" });
|
|
50
50
|
try {
|
|
51
51
|
const doc = await parseDocx(buffer, {
|
|
52
52
|
detectVariables: false,
|
|
53
|
-
preloadFonts: false
|
|
53
|
+
preloadFonts: false,
|
|
54
|
+
password: options.password
|
|
54
55
|
});
|
|
55
56
|
if (this.loadGeneration !== generation) return;
|
|
56
57
|
this.loadParsedDocument(doc);
|
|
@@ -43,7 +43,8 @@ declare function computeEffectiveHeaderFooterMargins({
|
|
|
43
43
|
/** Rendered header/footer content shared by every extender on a page. */
|
|
44
44
|
type HeaderFooterExtenderContent = Omit<EffectiveHeaderFooterMarginsInput, "margins" | "pageSize" | "warn">;
|
|
45
45
|
type ExtendSectionBreakMarginsInput = {
|
|
46
|
-
content: HeaderFooterExtenderContent;
|
|
46
|
+
content: HeaderFooterExtenderContent;
|
|
47
|
+
sectionContent?: HeaderFooterExtenderContent[] | undefined; /** Body page size and effective margins — the inheritance seed. */
|
|
47
48
|
bodyPageSize: {
|
|
48
49
|
w: number;
|
|
49
50
|
h: number;
|
|
@@ -65,6 +66,7 @@ type ExtendSectionBreakMarginsInput = {
|
|
|
65
66
|
*/
|
|
66
67
|
declare function extendSectionBreakMargins(sectionBreaks: SectionBreakBlock[], {
|
|
67
68
|
content,
|
|
69
|
+
sectionContent,
|
|
68
70
|
bodyPageSize,
|
|
69
71
|
bodyMargins,
|
|
70
72
|
warn
|
|
@@ -102,14 +102,16 @@ function computeEffectiveHeaderFooterMargins({ margins, headerContent, footerCon
|
|
|
102
102
|
* clamped reservation (and vice versa). Materializes `margins` on every
|
|
103
103
|
* non-inheriting break in place.
|
|
104
104
|
*/
|
|
105
|
-
function extendSectionBreakMargins(sectionBreaks, { content, bodyPageSize, bodyMargins, warn }) {
|
|
105
|
+
function extendSectionBreakMargins(sectionBreaks, { content, sectionContent, bodyPageSize, bodyMargins, warn }) {
|
|
106
106
|
let pageSize = bodyPageSize;
|
|
107
107
|
let margins = bodyMargins;
|
|
108
|
-
for (
|
|
108
|
+
for (let index = 0; index < sectionBreaks.length; index++) {
|
|
109
|
+
const sb = sectionBreaks[index];
|
|
110
|
+
if (!sb) continue;
|
|
109
111
|
if (!sb.pageSize && !sb.margins) continue;
|
|
110
112
|
pageSize = sb.pageSize ?? pageSize;
|
|
111
113
|
margins = computeHeaderFooterMarginExtender({
|
|
112
|
-
...content,
|
|
114
|
+
...sectionContent?.[index + 1] ?? content,
|
|
113
115
|
pageSize,
|
|
114
116
|
warn
|
|
115
117
|
})(sb.margins ?? margins);
|
|
@@ -236,6 +236,7 @@ const readTableRowAttrs = (node) => {
|
|
|
236
236
|
optionalNumber(attrs, "height", "tableRow.attrs.height", issues);
|
|
237
237
|
optionalOneOf(attrs, "heightRule", "tableRow.attrs.heightRule", issues, TABLE_ROW_HEIGHT_RULE_VALUES);
|
|
238
238
|
optionalBoolean(attrs, "isHeader", "tableRow.attrs.isHeader", issues);
|
|
239
|
+
optionalBoolean(attrs, "hidden", "tableRow.attrs.hidden", issues);
|
|
239
240
|
optionalRecord(attrs, "_originalFormatting", "tableRow.attrs._originalFormatting", issues);
|
|
240
241
|
return attrsResult(attrs, issues);
|
|
241
242
|
};
|
|
@@ -341,6 +341,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
341
341
|
if (attrs.styleId !== (orig.styleId ?? void 0)) if (attrs.styleId) result.styleId = attrs.styleId;
|
|
342
342
|
else delete result.styleId;
|
|
343
343
|
assignBooleanToggle(result, attrs, orig, "pageBreakBefore");
|
|
344
|
+
assignBooleanToggle(result, attrs, orig, "widowControl");
|
|
344
345
|
if (attrs.spacingExplicit !== orig.spacingExplicit) if (attrs.spacingExplicit) result.spacingExplicit = attrs.spacingExplicit;
|
|
345
346
|
else delete result.spacingExplicit;
|
|
346
347
|
const bidi = directionToBidi(attrs.direction);
|
|
@@ -350,7 +351,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
350
351
|
}
|
|
351
352
|
const outlineLevel = Reflect.get(attrs, "outlineLevel");
|
|
352
353
|
const bidi = directionToBidi(attrs.direction);
|
|
353
|
-
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)) return;
|
|
354
|
+
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)) return;
|
|
354
355
|
const f = {};
|
|
355
356
|
if (attrs.alignment) f.alignment = attrs.alignment;
|
|
356
357
|
if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
|
|
@@ -373,6 +374,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
373
374
|
if (attrs.contextualSpacing) f.contextualSpacing = attrs.contextualSpacing;
|
|
374
375
|
if (bidi != null) f.bidi = bidi;
|
|
375
376
|
if (attrs.pageBreakBefore != null) f.pageBreakBefore = attrs.pageBreakBefore;
|
|
377
|
+
if (attrs.widowControl != null) f.widowControl = attrs.widowControl;
|
|
376
378
|
return f;
|
|
377
379
|
}
|
|
378
380
|
/**
|
|
@@ -1397,9 +1399,11 @@ function tableRowAttrsToFormatting(attrs) {
|
|
|
1397
1399
|
else delete result.heightRule;
|
|
1398
1400
|
if (attrs.isHeader !== (orig.header ?? void 0)) if (attrs.isHeader) result.header = attrs.isHeader;
|
|
1399
1401
|
else delete result.header;
|
|
1402
|
+
if (attrs.hidden !== (orig.hidden ?? void 0)) if (attrs.hidden) result.hidden = attrs.hidden;
|
|
1403
|
+
else delete result.hidden;
|
|
1400
1404
|
return result;
|
|
1401
1405
|
}
|
|
1402
|
-
if (!(attrs.height || attrs.isHeader)) return;
|
|
1406
|
+
if (!(attrs.height || attrs.isHeader || attrs.hidden)) return;
|
|
1403
1407
|
const f = {};
|
|
1404
1408
|
if (attrs.height) f.height = {
|
|
1405
1409
|
value: attrs.height,
|
|
@@ -1407,6 +1411,7 @@ function tableRowAttrsToFormatting(attrs) {
|
|
|
1407
1411
|
};
|
|
1408
1412
|
if (attrs.heightRule) f.heightRule = attrs.heightRule;
|
|
1409
1413
|
if (attrs.isHeader) f.header = attrs.isHeader;
|
|
1414
|
+
if (attrs.hidden) f.hidden = attrs.hidden;
|
|
1410
1415
|
return f;
|
|
1411
1416
|
}
|
|
1412
1417
|
/**
|
|
@@ -11,6 +11,7 @@ import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
|
11
11
|
import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
|
|
12
12
|
import { schema } from "../schema/index.js";
|
|
13
13
|
//#region src/prosemirror/conversion/toProseDoc.ts
|
|
14
|
+
const TOC_STYLE_ID = /^TOC\d*$/iu;
|
|
14
15
|
/**
|
|
15
16
|
* Convert a Document to a ProseMirror document
|
|
16
17
|
*
|
|
@@ -80,6 +81,7 @@ function convertBlockSdt(blockSdt, convertBlocks) {
|
|
|
80
81
|
*/
|
|
81
82
|
function convertParagraph(paragraph, styleResolver, activeCommentIds, extraRunFormatting, tableParagraphOverlay) {
|
|
82
83
|
const attrs = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
|
|
84
|
+
const isTocParagraph = TOC_STYLE_ID.test(paragraph.formatting?.styleId ?? "");
|
|
83
85
|
const inlineNodes = [];
|
|
84
86
|
let inlineOffset = 0;
|
|
85
87
|
let bookmarksArr;
|
|
@@ -99,10 +101,12 @@ function convertParagraph(paragraph, styleResolver, activeCommentIds, extraRunFo
|
|
|
99
101
|
let styleRunFormatting;
|
|
100
102
|
if (styleResolver) styleRunFormatting = styleResolver.resolveParagraphStyle(paragraph.formatting?.styleId).runFormatting;
|
|
101
103
|
const paragraphRunFormatting = paragraph.formatting?.runProperties ? resolveTextFormatting(paragraph.formatting.runProperties, styleResolver) : void 0;
|
|
102
|
-
|
|
104
|
+
let inheritableParagraphRunFormatting;
|
|
105
|
+
if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkOnlyFormatting(paragraphRunFormatting);
|
|
103
106
|
const baseRunFormatting = mergeTextFormatting(styleRunFormatting, extraRunFormatting);
|
|
104
107
|
const defaultRunFormatting = mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
|
|
105
|
-
const getInheritedRunFormatting = (formatting) => {
|
|
108
|
+
const getInheritedRunFormatting = (formatting, fieldType) => {
|
|
109
|
+
if (fieldType === "TOC") return hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(baseRunFormatting, void 0, formatting) : baseRunFormatting;
|
|
106
110
|
if (!hasDirectRunFormatting(formatting)) return defaultRunFormatting;
|
|
107
111
|
return suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting);
|
|
108
112
|
};
|
|
@@ -252,11 +256,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
252
256
|
set("pageBreakBefore", formatting?.pageBreakBefore ?? stylePpr?.pageBreakBefore);
|
|
253
257
|
set("keepNext", formatting?.keepNext ?? stylePpr?.keepNext);
|
|
254
258
|
set("keepLines", formatting?.keepLines ?? stylePpr?.keepLines);
|
|
259
|
+
set("widowControl", formatting?.widowControl ?? stylePpr?.widowControl);
|
|
255
260
|
set("contextualSpacing", formatting?.contextualSpacing ?? stylePpr?.contextualSpacing);
|
|
256
261
|
set("runInWithNext", formatting?.runInWithNext ?? stylePpr?.runInWithNext);
|
|
257
262
|
set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
|
|
258
263
|
set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
|
|
259
|
-
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver));
|
|
264
|
+
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: !TOC_STYLE_ID.test(styleId ?? "") }));
|
|
260
265
|
if (!formatting?.numPr && stylePpr?.numPr && stylePpr.numPr.numId !== 0) {
|
|
261
266
|
attrs.numPr = stylePpr.numPr;
|
|
262
267
|
attrs.numPrFromStyle = stylePpr.numPr;
|
|
@@ -278,6 +283,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
278
283
|
set("pageBreakBefore", formatting?.pageBreakBefore);
|
|
279
284
|
set("keepNext", formatting?.keepNext);
|
|
280
285
|
set("keepLines", formatting?.keepLines);
|
|
286
|
+
set("widowControl", formatting?.widowControl);
|
|
281
287
|
set("runInWithNext", formatting?.runInWithNext);
|
|
282
288
|
set("outlineLevel", formatting?.outlineLevel);
|
|
283
289
|
set("direction", directionFromBidi(formatting?.bidi));
|
|
@@ -381,7 +387,7 @@ function hasDirectRunFormatting(formatting) {
|
|
|
381
387
|
return Object.entries(formatting).some(([key, value]) => key !== "styleId" && value !== void 0);
|
|
382
388
|
}
|
|
383
389
|
function stripParagraphMarkOnlyFormatting(formatting) {
|
|
384
|
-
const { highlight: _h, shading: _s, ...rest } = formatting;
|
|
390
|
+
const { allCaps: _ac, highlight: _h, shading: _s, smallCaps: _sc, ...rest } = formatting;
|
|
385
391
|
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
386
392
|
}
|
|
387
393
|
function suppressParagraphMarkFormatting(base, paragraphMark, direct) {
|
|
@@ -411,10 +417,10 @@ function resolveTextFormatting(formatting, styleResolver) {
|
|
|
411
417
|
if (!styleResolver) return formatting;
|
|
412
418
|
return mergeTextFormatting(styleResolver.resolveRunStyle(formatting.styleId), formatting);
|
|
413
419
|
}
|
|
414
|
-
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver) {
|
|
420
|
+
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
|
|
415
421
|
const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
416
422
|
const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
|
|
417
|
-
const rawParagraphMarkRpr = formatting?.runProperties;
|
|
423
|
+
const rawParagraphMarkRpr = options.includeParagraphMarkRunProperties === false ? void 0 : formatting?.runProperties;
|
|
418
424
|
const characterStyleRpr = rawParagraphMarkRpr?.styleId !== void 0 ? styleResolver.getRunStyleOwnProperties(rawParagraphMarkRpr.styleId) : void 0;
|
|
419
425
|
const paragraphRunProperties = rawParagraphMarkRpr ? stripParagraphMarkOnlyFormatting(mergeTextFormatting(characterStyleRpr, rawParagraphMarkRpr) ?? {}) : void 0;
|
|
420
426
|
return mergeTextFormatting(mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr), paragraphRunProperties);
|
|
@@ -599,6 +605,7 @@ function convertTableRow(row, styleResolver, isHeaderRow, columnWidths, totalWid
|
|
|
599
605
|
const attrs = { isHeader: !!row.formatting?.header };
|
|
600
606
|
if (row.formatting?.height?.value !== void 0) attrs.height = row.formatting.height.value;
|
|
601
607
|
if (row.formatting?.heightRule) attrs.heightRule = row.formatting.heightRule;
|
|
608
|
+
if (row.formatting?.hidden) attrs.hidden = true;
|
|
602
609
|
if (row.formatting) attrs._originalFormatting = row.formatting;
|
|
603
610
|
const numCells = row.cells.length;
|
|
604
611
|
const isFirstRow = rowIndex === 0;
|
|
@@ -769,7 +776,7 @@ function convertField(field, getInheritedRunFormatting, styleResolver) {
|
|
|
769
776
|
if (!fieldFormatting && r.formatting) fieldFormatting = r.formatting;
|
|
770
777
|
}
|
|
771
778
|
if (!fieldFormatting && field.type === "complexField" && field.fieldResult.length === 0) fieldFormatting = field.formatting;
|
|
772
|
-
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting);
|
|
779
|
+
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
|
|
773
780
|
const { marks } = buildRunMarks(fieldFormatting, inheritedFormatting, styleResolver);
|
|
774
781
|
return schema.node("field", {
|
|
775
782
|
fieldType: field.fieldType,
|
|
@@ -213,6 +213,7 @@ const paragraphNodeSpec = {
|
|
|
213
213
|
renderedPageBreakBefore: { default: null },
|
|
214
214
|
keepNext: { default: null },
|
|
215
215
|
keepLines: { default: null },
|
|
216
|
+
widowControl: { default: null },
|
|
216
217
|
contextualSpacing: { default: null },
|
|
217
218
|
runInWithNext: { default: null },
|
|
218
219
|
defaultTextFormatting: { default: null },
|