@stll/folio-core 0.8.0 → 0.9.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 +39 -0
- package/dist/ai-edits/apply.js +18 -4
- package/dist/ai-edits/headless.d.ts +31 -4
- package/dist/ai-edits/headless.js +148 -35
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/snapshot.js +40 -3
- package/dist/ai-edits/types.d.ts +2 -1
- package/dist/compat/eigenpal.d.ts +6 -4
- package/dist/compat/eigenpal.js +5 -3
- package/dist/controller/latestRequestGate.d.ts +13 -0
- package/dist/controller/latestRequestGate.js +16 -0
- package/dist/controller/layoutPipeline.js +12 -1
- package/dist/document-operations.d.ts +10 -3
- package/dist/document-operations.js +29 -14
- package/dist/docx/blockContentParser.js +2 -2
- package/dist/docx/commentParser.js +1 -1
- package/dist/docx/compatibility.d.ts +3 -7
- package/dist/docx/compatibility.js +0 -11
- package/dist/docx/encryption/agileDecryption.js +1 -1
- package/dist/docx/encryption/encryptionInfo.js +1 -1
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/fontTableParser.d.ts +6 -0
- package/dist/docx/fontTableParser.js +72 -0
- package/dist/docx/groupDrawingParser.js +7 -2
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/normalizeBaseDirection.js +1 -1
- package/dist/docx/numberingParser.js +1 -0
- package/dist/docx/paragraphParser.js +12 -1
- package/dist/docx/parser.d.ts +1 -1
- package/dist/docx/parser.js +12 -9
- package/dist/docx/rezip.js +70 -5
- package/dist/docx/runConsolidator.js +4 -0
- package/dist/docx/runParser.js +19 -1
- package/dist/docx/selectiveSave.js +3 -3
- package/dist/docx/serializer/fontTableSerializer.d.ts +6 -0
- package/dist/docx/serializer/fontTableSerializer.js +26 -0
- package/dist/docx/serializer/headerFooterSerializer.js +1 -1
- package/dist/docx/serializer/paragraphSerializer.js +4 -0
- package/dist/docx/serializer/runSerializer.js +7 -0
- package/dist/docx/serializer/settingsSerializer.d.ts +6 -0
- package/dist/docx/serializer/settingsSerializer.js +16 -0
- package/dist/docx/serializer/stylesSerializer.d.ts +6 -0
- package/dist/docx/serializer/stylesSerializer.js +56 -0
- package/dist/docx/serializer/tableSerializer.js +25 -26
- package/dist/docx/serializer/themeSerializer.d.ts +6 -0
- package/dist/docx/serializer/themeSerializer.js +36 -0
- package/dist/docx/settingsParser.js +46 -0
- package/dist/docx/styleParser.js +26 -1
- package/dist/docx/tableParser.js +11 -1
- package/dist/docx/vmlImageParser.js +1 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
- package/dist/i18n/messages/catalogs.gen.js +5910 -5910
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +6 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +51 -14
- package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
- package/dist/layout-bridge/engine/measuring/index.js +2 -1
- package/dist/layout-engine/index.js +36 -28
- package/dist/layout-engine/measure/cache.js +11 -3
- package/dist/layout-engine/measure/font-metrics.worker.js +1 -0
- package/dist/layout-engine/measure/index.d.ts +2 -1
- package/dist/layout-engine/measure/index.js +2 -1
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +33 -0
- package/dist/layout-engine/measure/lineBreakProvider.js +252 -0
- package/dist/layout-engine/measure/lineBreaks.d.ts +7 -2
- package/dist/layout-engine/measure/lineBreaks.js +11 -18
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +12 -6
- package/dist/layout-engine/measure/measureBlocks.d.ts +1 -2
- package/dist/layout-engine/measure/measureBlocks.js +6 -36
- package/dist/layout-engine/measure/measureContainer.js +32 -9
- package/dist/layout-engine/measure/measureHelpers.js +5 -2
- package/dist/layout-engine/measure/measureParagraph.js +335 -72
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -1
- package/dist/layout-engine/measure/measureWorker.d.ts +2 -2
- package/dist/layout-engine/measure/measureWorker.js +8 -19
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +3 -14
- package/dist/layout-engine/measure/tableCellFloating.d.ts +10 -3
- package/dist/layout-engine/measure/tableCellFloating.js +37 -29
- package/dist/layout-engine/measure/tableCellFlow.d.ts +27 -0
- package/dist/layout-engine/measure/tableCellFlow.js +73 -0
- package/dist/layout-engine/measure/tableCellGrid.js +1 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +6 -1
- package/dist/layout-engine/renderedBreakReconciliation.js +34 -11
- package/dist/layout-engine/tableRowBreak.d.ts +5 -2
- package/dist/layout-engine/tableRowBreak.js +62 -29
- package/dist/layout-engine/types.d.ts +40 -7
- package/dist/layout-painter/anchoredImagePosition.d.ts +23 -0
- package/dist/layout-painter/anchoredImagePosition.js +95 -0
- package/dist/layout-painter/borderStroke.d.ts +23 -0
- package/dist/layout-painter/borderStroke.js +39 -0
- package/dist/layout-painter/renderImage.d.ts +5 -4
- package/dist/layout-painter/renderImage.js +18 -4
- package/dist/layout-painter/renderPage.d.ts +2 -27
- package/dist/layout-painter/renderPage.js +13 -99
- package/dist/layout-painter/renderParagraph.js +41 -23
- package/dist/layout-painter/renderTable.d.ts +2 -0
- package/dist/layout-painter/renderTable.js +223 -43
- package/dist/managers/DocumentLoaderManager.d.ts +1 -1
- package/dist/managers/DocumentLoaderManager.js +2 -2
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +21 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +33 -18
- package/dist/prosemirror/conversion/toProseDoc.js +50 -18
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +7 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/LanguageExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/marks/LanguageExtension.js +30 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +1 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +12 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +4 -2
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +6 -1
- package/dist/prosemirror/schema/nodes.d.ts +13 -11
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +3 -1
- package/dist/prosemirror/utils/tabCalculator.js +12 -10
- package/dist/prosemirror/validation.js +4 -1
- package/dist/redline.js +13 -3
- package/dist/server.d.ts +6 -3
- package/dist/server.js +5 -2
- package/dist/style-sets/extract.d.ts +35 -0
- package/dist/style-sets/extract.js +123 -0
- package/dist/style-sets/stellaStyle.d.ts +13 -0
- package/dist/style-sets/stellaStyle.js +516 -0
- package/dist/style-sets/types.d.ts +31 -0
- package/dist/style-sets/types.js +5 -0
- package/dist/utils/createDocument.d.ts +12 -2
- package/dist/utils/createDocument.js +42 -31
- package/dist/utils/fontResolver.js +6 -6
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
- package/dist/utils/paragraphFormattingMerge.js +14 -4
- package/package.json +5 -1
- package/dist/docx/capabilities.d.ts +0 -41
- package/dist/docx/capabilities.js +0 -322
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
import { isFloatingTextBoxBlock } from "./types.js";
|
|
2
1
|
import { measureParagraph } from "./measure/measureParagraph.js";
|
|
2
|
+
import { isEmptyParagraph } from "./paragraphSpacing.js";
|
|
3
|
+
import { createTableCellFlowState, placeTableCellBlock } from "./measure/tableCellFlow.js";
|
|
3
4
|
import { buildTableCellFloatingZones, getTableCellContentWidth, getTableCellFloatingImages } from "./measure/tableCellFloating.js";
|
|
4
5
|
//#region src/layout-engine/tableRowBreak.ts
|
|
5
6
|
/**
|
|
6
7
|
* Table row-break geometry. Ported from eigenpal/docx-editor#698 (folio subset).
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* was clipped (content lost; upstream #570).
|
|
9
|
+
* Table rows may break across flow regions unless `cantSplit` is set. When a
|
|
10
|
+
* permitted row exceeds the current region, the portion that fits stays and
|
|
11
|
+
* the rest continues in the next region, broken between whole text lines and
|
|
12
|
+
* never through a glyph. This also prevents oversized rows from overflowing
|
|
13
|
+
* one page and clipping content (upstream #570).
|
|
14
14
|
*
|
|
15
15
|
* This computes, per row, the safe break offsets (the y of every line bottom in
|
|
16
16
|
* the row's cells) so the paginator can snap a break to the deepest whole line
|
|
17
17
|
* that still fits. Vertically-merged cells that span into a row are not modeled
|
|
18
18
|
* here yet (a separate follow-up); each row uses its own cells' content.
|
|
19
19
|
*/
|
|
20
|
+
const BREAK_OFFSET_EPSILON = .01;
|
|
20
21
|
const DEFAULT_TABLE_CELL_PADDING_TOP = 1;
|
|
21
|
-
function getAtomicBlockHeight(measure) {
|
|
22
|
-
if ("totalHeight" in measure) return measure.totalHeight;
|
|
23
|
-
if ("height" in measure) return measure.height;
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
22
|
function isInsideRange(offset, range) {
|
|
27
23
|
return offset > range.top && offset < range.bottom;
|
|
28
24
|
}
|
|
@@ -39,6 +35,10 @@ function shiftCellGeometry(geometry, offset) {
|
|
|
39
35
|
unsafeRanges: geometry.unsafeRanges.map((range) => ({
|
|
40
36
|
top: range.top + offset,
|
|
41
37
|
bottom: range.bottom + offset
|
|
38
|
+
})),
|
|
39
|
+
suppressibleLeadingRanges: geometry.suppressibleLeadingRanges.map((range) => ({
|
|
40
|
+
top: range.top + offset,
|
|
41
|
+
bottom: range.bottom + offset
|
|
42
42
|
}))
|
|
43
43
|
};
|
|
44
44
|
}
|
|
@@ -46,22 +46,28 @@ function shiftCellGeometry(geometry, offset) {
|
|
|
46
46
|
function cellBreakGeometry(cell, measure) {
|
|
47
47
|
const bottoms = [];
|
|
48
48
|
const unsafeRanges = [];
|
|
49
|
+
const suppressibleLeadingRanges = [];
|
|
49
50
|
const cellBlocks = cell?.blocks;
|
|
50
51
|
const blockMeasures = measure.blocks;
|
|
51
52
|
const padTop = cell?.padding?.top ?? DEFAULT_TABLE_CELL_PADDING_TOP;
|
|
52
53
|
const contentWidth = getTableCellContentWidth(cell, measure);
|
|
53
54
|
const floatingZones = buildTableCellFloatingZones(cell !== void 0 ? getTableCellFloatingImages(cell, measure, contentWidth) : [], contentWidth);
|
|
54
|
-
|
|
55
|
-
let paragraphY = 0;
|
|
55
|
+
const flowState = createTableCellFlowState();
|
|
56
56
|
for (let i = 0; i < blockMeasures.length; i++) {
|
|
57
57
|
let blockMeasure = blockMeasures[i];
|
|
58
58
|
if (blockMeasure?.kind === "paragraph") {
|
|
59
59
|
const block = cellBlocks?.[i];
|
|
60
|
-
if (block?.kind
|
|
60
|
+
if (block?.kind !== "paragraph") continue;
|
|
61
|
+
if (floatingZones.length > 0) blockMeasure = measureParagraph(block, contentWidth, {
|
|
61
62
|
floatingZones,
|
|
62
|
-
paragraphYOffset:
|
|
63
|
+
paragraphYOffset: placeTableCellBlock({ ...flowState }, block, blockMeasure).contentTop
|
|
64
|
+
});
|
|
65
|
+
const placement = placeTableCellBlock(flowState, block, blockMeasure);
|
|
66
|
+
if (placement.leadingSpacing > 0 && isEmptyParagraph(block)) suppressibleLeadingRanges.push({
|
|
67
|
+
top: padTop + placement.top,
|
|
68
|
+
bottom: padTop + placement.contentTop
|
|
63
69
|
});
|
|
64
|
-
|
|
70
|
+
let y = padTop + placement.contentTop;
|
|
65
71
|
for (const line of blockMeasure.lines) {
|
|
66
72
|
y += line.floatSkipBefore ?? 0;
|
|
67
73
|
const top = y;
|
|
@@ -72,16 +78,15 @@ function cellBreakGeometry(cell, measure) {
|
|
|
72
78
|
});
|
|
73
79
|
bottoms.push(y);
|
|
74
80
|
}
|
|
75
|
-
|
|
76
|
-
paragraphY += blockMeasure.totalHeight;
|
|
81
|
+
bottoms.push(padTop + flowState.height);
|
|
77
82
|
} else if (blockMeasure) {
|
|
78
83
|
const block = cellBlocks?.[i];
|
|
79
|
-
if (block
|
|
80
|
-
const
|
|
84
|
+
if (!block) continue;
|
|
85
|
+
const placement = placeTableCellBlock(flowState, block, blockMeasure);
|
|
86
|
+
const blockHeight = placement.contentHeight;
|
|
81
87
|
if (blockHeight > 0) {
|
|
82
|
-
const top =
|
|
83
|
-
y
|
|
84
|
-
paragraphY += blockHeight;
|
|
88
|
+
const top = padTop + placement.contentTop;
|
|
89
|
+
const y = top + blockHeight;
|
|
85
90
|
unsafeRanges.push({
|
|
86
91
|
top,
|
|
87
92
|
bottom: y
|
|
@@ -92,9 +97,26 @@ function cellBreakGeometry(cell, measure) {
|
|
|
92
97
|
}
|
|
93
98
|
return {
|
|
94
99
|
bottoms,
|
|
95
|
-
unsafeRanges
|
|
100
|
+
unsafeRanges,
|
|
101
|
+
suppressibleLeadingRanges
|
|
96
102
|
};
|
|
97
103
|
}
|
|
104
|
+
const continuationSkipForCell = (geometry, offset) => {
|
|
105
|
+
if (!geometry.unsafeRanges.some(({ bottom }) => bottom > offset + BREAK_OFFSET_EPSILON)) return;
|
|
106
|
+
const leadingRange = geometry.suppressibleLeadingRanges.find(({ top, bottom }) => top <= offset + BREAK_OFFSET_EPSILON && bottom > offset + BREAK_OFFSET_EPSILON);
|
|
107
|
+
return leadingRange ? leadingRange.bottom - offset : 0;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Leading spacing before an empty paragraph is consumed when a split row
|
|
111
|
+
* resumes at the top of a fresh flow region. Only a whitespace band shared by
|
|
112
|
+
* every cell with remaining content is suppressible; non-empty paragraphs,
|
|
113
|
+
* line boxes, cell padding, and explicit row height retain authored space.
|
|
114
|
+
*/
|
|
115
|
+
const continuationSkipAfter = (geometries, offset) => {
|
|
116
|
+
const skips = geometries.map((geometry) => continuationSkipForCell(geometry, offset)).filter((skip) => skip !== void 0);
|
|
117
|
+
if (skips.length === 0 || skips.some((skip) => skip <= BREAK_OFFSET_EPSILON)) return 0;
|
|
118
|
+
return Math.min(...skips);
|
|
119
|
+
};
|
|
98
120
|
/** Build break geometry for a table from its block + measure. */
|
|
99
121
|
function buildTableRowBreakInfo(block, measure) {
|
|
100
122
|
const rowCount = measure.rows.length;
|
|
@@ -106,6 +128,7 @@ function buildTableRowBreakInfo(block, measure) {
|
|
|
106
128
|
}
|
|
107
129
|
rowTops.push(acc);
|
|
108
130
|
const breakOffsets = [];
|
|
131
|
+
const continuationSkips = [];
|
|
109
132
|
for (let r = 0; r < rowCount; r++) {
|
|
110
133
|
const rowHeight = measure.rows[r]?.height ?? 0;
|
|
111
134
|
const offsets = /* @__PURE__ */ new Set();
|
|
@@ -121,14 +144,24 @@ function buildTableRowBreakInfo(block, measure) {
|
|
|
121
144
|
cellGeometries.push(geometry);
|
|
122
145
|
for (const b of geometry.bottoms) if (b > 0 && b < rowHeight) offsets.add(b);
|
|
123
146
|
}
|
|
124
|
-
const
|
|
125
|
-
breakOffsets.push(
|
|
147
|
+
const sortedOffsets = [...offsets].filter((offset) => offset === rowHeight || cellGeometries.every((geometry) => geometry.unsafeRanges.every((range) => !isInsideRange(offset, range)))).sort((a, b) => a - b);
|
|
148
|
+
breakOffsets.push(sortedOffsets);
|
|
149
|
+
continuationSkips.push(sortedOffsets.map((offset) => continuationSkipAfter(cellGeometries, offset)));
|
|
126
150
|
}
|
|
127
151
|
return {
|
|
128
152
|
rowTops,
|
|
129
|
-
breakOffsets
|
|
153
|
+
breakOffsets,
|
|
154
|
+
continuationSkips
|
|
130
155
|
};
|
|
131
156
|
}
|
|
157
|
+
/** Leading empty-paragraph whitespace to consume when a row resumes after `offset`. */
|
|
158
|
+
function getRowContinuationSkip(info, rowIndex, offset) {
|
|
159
|
+
const offsets = info.breakOffsets[rowIndex];
|
|
160
|
+
const skips = info.continuationSkips[rowIndex];
|
|
161
|
+
const index = offsets?.findIndex((candidate) => Math.abs(candidate - offset) <= BREAK_OFFSET_EPSILON);
|
|
162
|
+
if (index === void 0 || index < 0) return 0;
|
|
163
|
+
return skips?.[index] ?? 0;
|
|
164
|
+
}
|
|
132
165
|
/**
|
|
133
166
|
* Given a row and how much of it has already been placed (`fromOffset`), return
|
|
134
167
|
* how many more px can be placed ending on a whole line, without exceeding
|
|
@@ -147,4 +180,4 @@ function snapRowBreak(info, rowIndex, fromOffset, maxSlice) {
|
|
|
147
180
|
return best;
|
|
148
181
|
}
|
|
149
182
|
//#endregion
|
|
150
|
-
export { buildTableRowBreakInfo, snapRowBreak };
|
|
183
|
+
export { buildTableRowBreakInfo, getRowContinuationSkip, snapRowBreak };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OutlineStyleAttr } from "../types/documentEnumValues.js";
|
|
2
|
-
import { ImagePosition, ImageWrap, SdtProperties, SdtType, ShapeTextBody, TableWidthType } from "@stll/docx-core/model";
|
|
2
|
+
import { ImagePosition, ImageWrap, SdtProperties, SdtType, ShapeTextBody, TableCellFormatting, TableWidthType } from "@stll/docx-core/model";
|
|
3
3
|
|
|
4
4
|
//#region src/layout-engine/types.d.ts
|
|
5
5
|
declare namespace types_d_exports {
|
|
@@ -38,7 +38,12 @@ type RunFormatting = {
|
|
|
38
38
|
* `segmentByScript`) so wrapping stays correct. Absent means CJK falls back
|
|
39
39
|
* to `fontFamily`.
|
|
40
40
|
*/
|
|
41
|
-
eastAsiaFontFamily?: string;
|
|
41
|
+
eastAsiaFontFamily?: string; /** Run language metadata resolved from `w:lang`. */
|
|
42
|
+
language?: {
|
|
43
|
+
val?: string;
|
|
44
|
+
eastAsia?: string;
|
|
45
|
+
bidi?: string;
|
|
46
|
+
};
|
|
42
47
|
fontSize?: number;
|
|
43
48
|
letterSpacing?: number;
|
|
44
49
|
superscript?: boolean;
|
|
@@ -164,7 +169,8 @@ type ImageRun = {
|
|
|
164
169
|
distTop?: number;
|
|
165
170
|
distBottom?: number;
|
|
166
171
|
distLeft?: number;
|
|
167
|
-
distRight?: number;
|
|
172
|
+
distRight?: number; /** Use the image box as the exact line height for an embedded-object preview. */
|
|
173
|
+
exactLineHeight?: boolean;
|
|
168
174
|
/**
|
|
169
175
|
* wp:srcRect crop fractions in [0, 1]; emit as CSS `clip-path: inset(...)`
|
|
170
176
|
* to match Word's visible region. eigenpal #424 (image-crop subset).
|
|
@@ -286,7 +292,26 @@ type ListNumPr = {
|
|
|
286
292
|
* Paragraph block attributes.
|
|
287
293
|
*/
|
|
288
294
|
type ParagraphAttrs = {
|
|
289
|
-
alignment?: "left" | "center" | "right" | "justify"; /**
|
|
295
|
+
alignment?: "left" | "center" | "right" | "justify"; /** East Asian first/last-character restrictions (`w:kinsoku`). */
|
|
296
|
+
kinsoku?: boolean; /** Hanging punctuation (`w:overflowPunct`), retained for layout policy. */
|
|
297
|
+
overflowPunctuation?: boolean; /** Exempt this paragraph from document automatic hyphenation. */
|
|
298
|
+
suppressAutoHyphens?: boolean; /** Document-wide automatic hyphenation controls retained for line layout. */
|
|
299
|
+
automaticHyphenation?: {
|
|
300
|
+
enabled: true;
|
|
301
|
+
doNotHyphenateCaps?: boolean;
|
|
302
|
+
consecutiveLineLimit?: number;
|
|
303
|
+
}; /** Document-wide custom line-edge characters and compatibility behavior. */
|
|
304
|
+
lineBreakRules?: {
|
|
305
|
+
noLineBreaksBefore?: {
|
|
306
|
+
language?: string;
|
|
307
|
+
characters: string;
|
|
308
|
+
};
|
|
309
|
+
noLineBreaksAfter?: {
|
|
310
|
+
language?: string;
|
|
311
|
+
characters: string;
|
|
312
|
+
};
|
|
313
|
+
useLegacyEthiopicAmharicRules?: boolean;
|
|
314
|
+
}; /** OOXML outline level (`w:outlineLvl`), where zero is the top level. */
|
|
290
315
|
outlineLevel?: number;
|
|
291
316
|
spacing?: ParagraphSpacing; /** Spacing sides resolved from OOXML automatic paragraph spacing. */
|
|
292
317
|
automaticSpacing?: {
|
|
@@ -338,7 +363,8 @@ type ParagraphAttrs = {
|
|
|
338
363
|
listIsBullet?: boolean;
|
|
339
364
|
listMarkerHidden?: boolean;
|
|
340
365
|
listMarkerFontFamily?: string;
|
|
341
|
-
listMarkerFontSize?: number;
|
|
366
|
+
listMarkerFontSize?: number;
|
|
367
|
+
listMarkerBold?: boolean; /** Horizontal alignment of the marker around the paragraph's list anchor. */
|
|
342
368
|
listMarkerAlignment?: "left" | "center" | "right";
|
|
343
369
|
/**
|
|
344
370
|
* `w:suff` (§17.9.25) — what follows the marker before body text.
|
|
@@ -413,6 +439,8 @@ type CellBorders = {
|
|
|
413
439
|
bottom?: CellBorderSpec;
|
|
414
440
|
left?: CellBorderSpec;
|
|
415
441
|
right?: CellBorderSpec;
|
|
442
|
+
topLeftToBottomRight?: CellBorderSpec;
|
|
443
|
+
topRightToBottomLeft?: CellBorderSpec;
|
|
416
444
|
};
|
|
417
445
|
/**
|
|
418
446
|
* A table cell with content.
|
|
@@ -424,6 +452,7 @@ type TableCell = {
|
|
|
424
452
|
rowSpan?: number;
|
|
425
453
|
width?: number;
|
|
426
454
|
verticalAlign?: "top" | "center" | "bottom";
|
|
455
|
+
textDirection?: NonNullable<TableCellFormatting["textDirection"]>;
|
|
427
456
|
background?: string;
|
|
428
457
|
borders?: CellBorders; /** Per-cell padding in pixels (from w:tcMar or table-level w:tblCellMar) */
|
|
429
458
|
padding?: {
|
|
@@ -449,7 +478,8 @@ type TableRow = {
|
|
|
449
478
|
gridAfter?: number;
|
|
450
479
|
height?: number;
|
|
451
480
|
heightRule?: "auto" | "atLeast" | "exact";
|
|
452
|
-
isHeader?: boolean;
|
|
481
|
+
isHeader?: boolean; /** `w:cantSplit`: keep this row in one flow region. */
|
|
482
|
+
cantSplit?: boolean;
|
|
453
483
|
hidden?: boolean;
|
|
454
484
|
};
|
|
455
485
|
/**
|
|
@@ -669,7 +699,10 @@ type MeasuredLine = {
|
|
|
669
699
|
* no usable horizontal room at the natural line Y. Painters render this
|
|
670
700
|
* as marginTop on the line element; measurement adds it to totalHeight.
|
|
671
701
|
*/
|
|
672
|
-
floatSkipBefore?: number;
|
|
702
|
+
floatSkipBefore?: number; /** Decorative hyphen inserted at a dictionary break without changing source text. */
|
|
703
|
+
discretionaryHyphen?: {
|
|
704
|
+
runIndex: number;
|
|
705
|
+
};
|
|
673
706
|
};
|
|
674
707
|
/**
|
|
675
708
|
* Measurement result for a paragraph block.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ImageRun } from "../layout-engine/types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/layout-painter/anchoredImagePosition.d.ts
|
|
4
|
+
type PageGeometry = {
|
|
5
|
+
pageWidth: number;
|
|
6
|
+
pageHeight: number;
|
|
7
|
+
marginLeft: number;
|
|
8
|
+
marginTop: number;
|
|
9
|
+
marginRight: number;
|
|
10
|
+
marginBottom: number;
|
|
11
|
+
contentWidth: number;
|
|
12
|
+
contentHeight: number;
|
|
13
|
+
};
|
|
14
|
+
/** Coordinates relative to the page content area's top-left corner. */
|
|
15
|
+
type AnchoredImagePosition = {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
side: "left" | "right";
|
|
19
|
+
};
|
|
20
|
+
/** Resolve an anchored image into page-content-relative coordinates. */
|
|
21
|
+
declare function resolveAnchoredImagePosition(imgRun: ImageRun, fragmentY: number, geometry: PageGeometry): AnchoredImagePosition;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { AnchoredImagePosition, PageGeometry, resolveAnchoredImagePosition };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { emuToPixels } from "./renderUtils.js";
|
|
2
|
+
//#region src/layout-painter/anchoredImagePosition.ts
|
|
3
|
+
function resolveHorizontalBand(relativeTo, geometry) {
|
|
4
|
+
switch (relativeTo) {
|
|
5
|
+
case "page": return {
|
|
6
|
+
baseX: -geometry.marginLeft,
|
|
7
|
+
bandWidth: geometry.pageWidth
|
|
8
|
+
};
|
|
9
|
+
case "leftMargin":
|
|
10
|
+
case "insideMargin": return {
|
|
11
|
+
baseX: -geometry.marginLeft,
|
|
12
|
+
bandWidth: geometry.marginLeft
|
|
13
|
+
};
|
|
14
|
+
case "rightMargin":
|
|
15
|
+
case "outsideMargin": return {
|
|
16
|
+
baseX: geometry.contentWidth,
|
|
17
|
+
bandWidth: geometry.marginRight
|
|
18
|
+
};
|
|
19
|
+
case "character": return {
|
|
20
|
+
baseX: 0,
|
|
21
|
+
bandWidth: 0
|
|
22
|
+
};
|
|
23
|
+
default: return {
|
|
24
|
+
baseX: 0,
|
|
25
|
+
bandWidth: geometry.contentWidth
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function resolveVerticalBand(relativeTo, fragmentY, geometry) {
|
|
30
|
+
switch (relativeTo) {
|
|
31
|
+
case "page": return {
|
|
32
|
+
baseY: -geometry.marginTop,
|
|
33
|
+
bandHeight: geometry.pageHeight
|
|
34
|
+
};
|
|
35
|
+
case "topMargin": return {
|
|
36
|
+
baseY: -geometry.marginTop,
|
|
37
|
+
bandHeight: geometry.marginTop
|
|
38
|
+
};
|
|
39
|
+
case "bottomMargin": return {
|
|
40
|
+
baseY: geometry.contentHeight,
|
|
41
|
+
bandHeight: geometry.marginBottom
|
|
42
|
+
};
|
|
43
|
+
case "paragraph":
|
|
44
|
+
case "line": return {
|
|
45
|
+
baseY: fragmentY,
|
|
46
|
+
bandHeight: 0
|
|
47
|
+
};
|
|
48
|
+
default: return {
|
|
49
|
+
baseY: 0,
|
|
50
|
+
bandHeight: geometry.contentHeight
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Resolve an anchored image into page-content-relative coordinates. */
|
|
55
|
+
function resolveAnchoredImagePosition(imgRun, fragmentY, geometry) {
|
|
56
|
+
const position = imgRun.position;
|
|
57
|
+
const contentWidth = geometry.contentWidth;
|
|
58
|
+
let side = "left";
|
|
59
|
+
let x = 0;
|
|
60
|
+
if (position?.horizontal) {
|
|
61
|
+
const h = position.horizontal;
|
|
62
|
+
const { baseX, bandWidth } = resolveHorizontalBand(h.relativeTo, geometry);
|
|
63
|
+
const horizontalHasBand = h.relativeTo !== "character";
|
|
64
|
+
if (h.align === "right" || h.align === "outside") {
|
|
65
|
+
side = "right";
|
|
66
|
+
x = horizontalHasBand ? baseX + bandWidth - imgRun.width : 0;
|
|
67
|
+
} else if (h.align === "left" || h.align === "inside") x = baseX;
|
|
68
|
+
else if (h.align === "center") x = horizontalHasBand ? baseX + (bandWidth - imgRun.width) / 2 : 0;
|
|
69
|
+
else if (h.posOffset !== void 0) {
|
|
70
|
+
x = baseX + emuToPixels(h.posOffset);
|
|
71
|
+
side = x > contentWidth / 2 ? "right" : "left";
|
|
72
|
+
} else x = baseX;
|
|
73
|
+
} else if (imgRun.cssFloat === "right") {
|
|
74
|
+
side = "right";
|
|
75
|
+
x = contentWidth - imgRun.width;
|
|
76
|
+
}
|
|
77
|
+
let y;
|
|
78
|
+
if (position?.vertical) {
|
|
79
|
+
const v = position.vertical;
|
|
80
|
+
const { baseY, bandHeight } = resolveVerticalBand(v.relativeTo, fragmentY, geometry);
|
|
81
|
+
const verticalHasBand = v.relativeTo !== "paragraph" && v.relativeTo !== "line";
|
|
82
|
+
if (v.align === "top" || v.align === "inside") y = baseY;
|
|
83
|
+
else if (v.align === "center") y = verticalHasBand ? baseY + (bandHeight - imgRun.height) / 2 : fragmentY;
|
|
84
|
+
else if (v.align === "bottom" || v.align === "outside") y = verticalHasBand ? baseY + bandHeight - imgRun.height : fragmentY;
|
|
85
|
+
else if (v.posOffset !== void 0) y = baseY + emuToPixels(v.posOffset);
|
|
86
|
+
else y = verticalHasBand ? baseY : fragmentY;
|
|
87
|
+
} else y = fragmentY;
|
|
88
|
+
return {
|
|
89
|
+
x,
|
|
90
|
+
y,
|
|
91
|
+
side
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { resolveAnchoredImagePosition };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BorderStyle, ParagraphBorders } from "../layout-engine/types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/layout-painter/borderStroke.d.ts
|
|
4
|
+
type CssBorderStroke = {
|
|
5
|
+
color: string;
|
|
6
|
+
style: string;
|
|
7
|
+
width: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Preserve the optical weight of authored subpixel borders. CSS quantizes a
|
|
11
|
+
* fractional border width to one device pixel, so its color carries the
|
|
12
|
+
* fractional coverage while layout keeps the authored width.
|
|
13
|
+
*/
|
|
14
|
+
declare const resolveCssBorderStroke: (border: Pick<BorderStyle, "color" | "style" | "width">) => CssBorderStroke;
|
|
15
|
+
declare const borderStrokeToCss: (border: Pick<BorderStyle, "color" | "style" | "width">) => string;
|
|
16
|
+
type ParagraphBorderHorizontalOutsets = {
|
|
17
|
+
left: number;
|
|
18
|
+
right: number;
|
|
19
|
+
};
|
|
20
|
+
/** Resolve the outer horizontal edges of a paragraph border box. */
|
|
21
|
+
declare const resolveParagraphBorderHorizontalOutsets: (borders: ParagraphBorders, hasHorizontalRule: boolean) => ParagraphBorderHorizontalOutsets;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { borderStrokeToCss, resolveCssBorderStroke, resolveParagraphBorderHorizontalOutsets };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { pointsToPixels } from "../utils/units.js";
|
|
2
|
+
//#region src/layout-painter/borderStroke.ts
|
|
3
|
+
const DEFAULT_BORDER_COLOR = "#000000";
|
|
4
|
+
const DEFAULT_BORDER_STYLE = "solid";
|
|
5
|
+
const CSS_HAIRLINE_WIDTH = 1;
|
|
6
|
+
const PARAGRAPH_RULE_ENDPOINT_OUTSET = pointsToPixels(1.5);
|
|
7
|
+
/**
|
|
8
|
+
* Preserve the optical weight of authored subpixel borders. CSS quantizes a
|
|
9
|
+
* fractional border width to one device pixel, so its color carries the
|
|
10
|
+
* fractional coverage while layout keeps the authored width.
|
|
11
|
+
*/
|
|
12
|
+
const resolveCssBorderStroke = (border) => {
|
|
13
|
+
const authoredWidth = border.width ?? CSS_HAIRLINE_WIDTH;
|
|
14
|
+
if (authoredWidth <= 0 || authoredWidth >= CSS_HAIRLINE_WIDTH) return {
|
|
15
|
+
color: border.color ?? DEFAULT_BORDER_COLOR,
|
|
16
|
+
style: border.style ?? DEFAULT_BORDER_STYLE,
|
|
17
|
+
width: Math.max(CSS_HAIRLINE_WIDTH, authoredWidth)
|
|
18
|
+
};
|
|
19
|
+
const coveragePercent = Number((authoredWidth * 100).toFixed(4));
|
|
20
|
+
return {
|
|
21
|
+
color: `color-mix(in srgb, ${border.color ?? DEFAULT_BORDER_COLOR} ${coveragePercent}%, transparent)`,
|
|
22
|
+
style: border.style ?? DEFAULT_BORDER_STYLE,
|
|
23
|
+
width: CSS_HAIRLINE_WIDTH
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const borderStrokeToCss = (border) => {
|
|
27
|
+
const stroke = resolveCssBorderStroke(border);
|
|
28
|
+
return `${stroke.width}px ${stroke.style} ${stroke.color}`;
|
|
29
|
+
};
|
|
30
|
+
/** Resolve the outer horizontal edges of a paragraph border box. */
|
|
31
|
+
const resolveParagraphBorderHorizontalOutsets = (borders, hasHorizontalRule) => {
|
|
32
|
+
const ruleOutset = hasHorizontalRule ? PARAGRAPH_RULE_ENDPOINT_OUTSET : 0;
|
|
33
|
+
return {
|
|
34
|
+
left: borders.left ? (borders.left.space ?? 0) + (borders.left.width ?? 0) : ruleOutset,
|
|
35
|
+
right: borders.right ? (borders.right.space ?? 0) + (borders.right.width ?? 0) : ruleOutset
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { borderStrokeToCss, resolveCssBorderStroke, resolveParagraphBorderHorizontalOutsets };
|
|
@@ -10,7 +10,7 @@ declare const IMAGE_CLASS_NAMES: {
|
|
|
10
10
|
imageAnchored: string;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
* Structural shape required to apply
|
|
13
|
+
* Structural shape required to apply OOXML per-image visual attributes:
|
|
14
14
|
* `wp:srcRect` crop fractions and `a:alphaModFix` opacity. `ImageRun` and
|
|
15
15
|
* `ImageBlock` both satisfy this, so callers don't need an adapter.
|
|
16
16
|
*/
|
|
@@ -32,10 +32,11 @@ type ImageVisualAttrs = {
|
|
|
32
32
|
* `0`) — that bug otherwise hides every plain image behind `opacity: 0`.
|
|
33
33
|
*/
|
|
34
34
|
declare function hasImageVisualAttrs(v: ImageVisualAttrs): boolean;
|
|
35
|
+
declare function hasImageCrop(v: ImageVisualAttrs): boolean;
|
|
35
36
|
/**
|
|
36
|
-
* Apply
|
|
37
|
+
* Apply an OOXML `<a:srcRect>` crop to an `<img>` whose parent already has
|
|
37
38
|
* `overflow: hidden` and is sized to the *visible* (cropped) dimensions
|
|
38
|
-
* (this matches `wp:extent` semantics:
|
|
39
|
+
* (this matches `wp:extent` semantics: the extent is the cropped
|
|
39
40
|
* frame, with `<a:stretch><a:fillRect/>` stretching the cropped source to
|
|
40
41
|
* fill it).
|
|
41
42
|
*
|
|
@@ -85,4 +86,4 @@ type RenderImageFragmentOptions = {
|
|
|
85
86
|
*/
|
|
86
87
|
declare function renderImageFragment(fragment: ImageFragment, block: ImageBlock, _measure: ImageMeasure, _context: RenderContext, options?: RenderImageFragmentOptions): HTMLElement;
|
|
87
88
|
//#endregion
|
|
88
|
-
export { IMAGE_CLASS_NAMES, ImageVisualAttrs, RenderImageFragmentOptions, applyImageVisualAttrs, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
89
|
+
export { IMAGE_CLASS_NAMES, ImageVisualAttrs, RenderImageFragmentOptions, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
@@ -18,12 +18,15 @@ const IMAGE_CLASS_NAMES = {
|
|
|
18
18
|
*/
|
|
19
19
|
function hasImageVisualAttrs(v) {
|
|
20
20
|
if (v.opacity != null && v.opacity < 1) return true;
|
|
21
|
+
return hasImageCrop(v);
|
|
22
|
+
}
|
|
23
|
+
function hasImageCrop(v) {
|
|
21
24
|
return Boolean(v.cropTop || v.cropRight || v.cropBottom || v.cropLeft);
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
24
|
-
* Apply
|
|
27
|
+
* Apply an OOXML `<a:srcRect>` crop to an `<img>` whose parent already has
|
|
25
28
|
* `overflow: hidden` and is sized to the *visible* (cropped) dimensions
|
|
26
|
-
* (this matches `wp:extent` semantics:
|
|
29
|
+
* (this matches `wp:extent` semantics: the extent is the cropped
|
|
27
30
|
* frame, with `<a:stretch><a:fillRect/>` stretching the cropped source to
|
|
28
31
|
* fill it).
|
|
29
32
|
*
|
|
@@ -54,8 +57,19 @@ function applyImageVisualAttrs(img, v) {
|
|
|
54
57
|
const fh = 1 / remainingH;
|
|
55
58
|
img.style.width = `${fw * 100}%`;
|
|
56
59
|
img.style.height = `${fh * 100}%`;
|
|
60
|
+
img.style.maxWidth = "none";
|
|
61
|
+
img.style.maxHeight = "none";
|
|
57
62
|
img.style.marginLeft = `${-left * fw * 100}%`;
|
|
58
|
-
img.style.
|
|
63
|
+
const existingTransform = img.style.transform;
|
|
64
|
+
if (existingTransform) {
|
|
65
|
+
const visibleCenterX = (left + 1 - right) * 50;
|
|
66
|
+
const visibleCenterY = (top + 1 - bottom) * 50;
|
|
67
|
+
img.style.transformOrigin = `${visibleCenterX}% ${visibleCenterY}%`;
|
|
68
|
+
}
|
|
69
|
+
if (top !== 0) {
|
|
70
|
+
const cropTransform = `translateY(${-top * 100}%)`;
|
|
71
|
+
img.style.transform = existingTransform ? `${existingTransform} ${cropTransform}` : cropTransform;
|
|
72
|
+
}
|
|
59
73
|
img.style.objectFit = "fill";
|
|
60
74
|
}
|
|
61
75
|
/**
|
|
@@ -127,4 +141,4 @@ function renderImageFragment(fragment, block, _measure, _context, options = {})
|
|
|
127
141
|
return containerEl;
|
|
128
142
|
}
|
|
129
143
|
//#endregion
|
|
130
|
-
export { IMAGE_CLASS_NAMES, applyImageVisualAttrs, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
144
|
+
export { IMAGE_CLASS_NAMES, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { FootnoteContent, HeaderFooterContent, ImageRun, Page, isFloatingImageRun } from "../layout-engine/types.js";
|
|
3
3
|
import { RenderContext, emuToPixels } from "./renderUtils.js";
|
|
4
|
+
import { AnchoredImagePosition, PageGeometry } from "./anchoredImagePosition.js";
|
|
4
5
|
import { BlockLookup } from "./index.js";
|
|
5
6
|
|
|
6
7
|
//#region src/layout-painter/renderPage.d.ts
|
|
@@ -157,32 +158,6 @@ declare function resolveHeaderFooterFloatLeft(width: number, h: {
|
|
|
157
158
|
align?: string;
|
|
158
159
|
alignment?: string;
|
|
159
160
|
} | undefined, layout: HeaderFooterLayoutInfo): string;
|
|
160
|
-
/**
|
|
161
|
-
* Page geometry needed to translate OOXML `relativeFrom` anchors into
|
|
162
|
-
* painter coordinates. All values are in CSS pixels. Mirrors the upstream
|
|
163
|
-
* (eigenpal docx-editor) `PageGeometry` shape introduced in #424 so the
|
|
164
|
-
* anchor math stays identical across the two codebases.
|
|
165
|
-
*/
|
|
166
|
-
type PageGeometry = {
|
|
167
|
-
pageWidth: number;
|
|
168
|
-
pageHeight: number;
|
|
169
|
-
marginLeft: number;
|
|
170
|
-
marginTop: number;
|
|
171
|
-
marginRight: number;
|
|
172
|
-
marginBottom: number;
|
|
173
|
-
contentWidth: number;
|
|
174
|
-
contentHeight: number;
|
|
175
|
-
};
|
|
176
|
-
/**
|
|
177
|
-
* Resolved on-page coordinates for an anchored floating image.
|
|
178
|
-
* `x` / `y` are in content-area-relative pixels (content origin = (0, 0)).
|
|
179
|
-
* `side` feeds the text-wrap exclusion zone helper.
|
|
180
|
-
*/
|
|
181
|
-
type AnchoredImagePosition = {
|
|
182
|
-
x: number;
|
|
183
|
-
y: number;
|
|
184
|
-
side: "left" | "right";
|
|
185
|
-
};
|
|
186
161
|
/**
|
|
187
162
|
* Resolve the on-page coordinates of an anchored floating image.
|
|
188
163
|
*
|
|
@@ -290,4 +265,4 @@ declare function findPageShellForPmPos(container: HTMLElement, pmPos: number): {
|
|
|
290
265
|
isExact: boolean;
|
|
291
266
|
} | null;
|
|
292
267
|
//#endregion
|
|
293
|
-
export { AnchoredImagePosition, FootnoteRenderItem, type HeaderFooterContent, HeaderFooterLayoutInfo, PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, PageFloatingImage, PageGeometry, PainterPaintedDetail, type RenderContext, RenderPageOptions, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft };
|
|
268
|
+
export { type AnchoredImagePosition, FootnoteRenderItem, type HeaderFooterContent, HeaderFooterLayoutInfo, PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, PageFloatingImage, type PageGeometry, PainterPaintedDetail, type RenderContext, RenderPageOptions, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft };
|