@stll/folio-core 0.49.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/headless.d.ts +37 -1
- package/dist/ai-edits/headless.js +47 -16
- package/dist/display-list/dom/renderDisplayListToDom.d.ts +10 -1
- package/dist/display-list/dom/renderDisplayListToDom.js +8 -7
- package/dist/display-list/html/renderDisplayListToHtml.d.ts +21 -0
- package/dist/display-list/html/renderDisplayListToHtml.js +126 -0
- package/dist/display-list/selectDisplayPages.d.ts +6 -0
- package/dist/display-list/selectDisplayPages.js +44 -0
- package/dist/export-pdf.d.ts +35 -2
- package/dist/export-pdf.js +51 -20
- package/dist/fonts/fontsourceFaces.d.ts +47 -0
- package/dist/fonts/fontsourceFaces.js +230 -0
- package/dist/layout-bridge/convert/flowBlockPostprocessing.d.ts +8 -0
- package/dist/layout-bridge/convert/flowBlockPostprocessing.js +106 -0
- package/dist/layout-bridge/convert/flowBorders.d.ts +17 -0
- package/dist/layout-bridge/convert/flowBorders.js +31 -0
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +111 -0
- package/dist/layout-bridge/convert/flowConversionShared.js +23 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +2 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +2 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +2 -1
- package/dist/layout-bridge/convert/imageConversion.d.ts +33 -0
- package/dist/layout-bridge/convert/imageConversion.js +118 -0
- package/dist/layout-bridge/convert/listMarkers.d.ts +28 -0
- package/dist/layout-bridge/convert/listMarkers.js +98 -0
- package/dist/layout-bridge/convert/noteReferences.d.ts +14 -0
- package/dist/layout-bridge/convert/noteReferences.js +29 -0
- package/dist/layout-bridge/convert/pageBreakSplitting.d.ts +16 -0
- package/dist/layout-bridge/convert/pageBreakSplitting.js +140 -0
- package/dist/layout-bridge/convert/paragraphAttrs.d.ts +20 -0
- package/dist/layout-bridge/convert/paragraphAttrs.js +234 -0
- package/dist/layout-bridge/convert/paragraphConversion.d.ts +12 -0
- package/dist/layout-bridge/convert/paragraphConversion.js +112 -0
- package/dist/layout-bridge/convert/paragraphRuns.d.ts +15 -0
- package/dist/layout-bridge/convert/paragraphRuns.js +281 -0
- package/dist/layout-bridge/convert/runFormattingMerge.d.ts +19 -0
- package/dist/layout-bridge/convert/runFormattingMerge.js +167 -0
- package/dist/layout-bridge/convert/runMarkFormatting.d.ts +11 -0
- package/dist/layout-bridge/convert/runMarkFormatting.js +291 -0
- package/dist/layout-bridge/convert/sectionBoundaries.d.ts +35 -0
- package/dist/layout-bridge/convert/sectionBoundaries.js +114 -0
- package/dist/layout-bridge/convert/tableConversion.d.ts +12 -0
- package/dist/layout-bridge/convert/tableConversion.js +303 -0
- package/dist/layout-bridge/convert/textBoxFill.d.ts +20 -0
- package/dist/layout-bridge/convert/textBoxFill.js +42 -0
- package/dist/layout-bridge/convert/textFormattingConversion.d.ts +22 -0
- package/dist/layout-bridge/convert/textFormattingConversion.js +120 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +5 -113
- package/dist/layout-bridge/convert/toFlowBlocks.js +11 -2082
- package/dist/layout-bridge/engine/hitTest.js +1 -1
- package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
- package/dist/layout-bridge/engine/measuring/index.js +2 -1
- package/dist/layout-bridge/engine/selectionRects.js +1 -1
- package/dist/layout-engine/imageLayout.d.ts +9 -0
- package/dist/layout-engine/imageLayout.js +48 -0
- package/dist/layout-engine/index.d.ts +3 -18
- package/dist/layout-engine/index.js +12 -937
- package/dist/layout-engine/layoutFlowShared.d.ts +6 -0
- package/dist/layout-engine/layoutFlowShared.js +8 -0
- package/dist/layout-engine/measure/crossRunWords.d.ts +45 -0
- package/dist/layout-engine/measure/crossRunWords.js +172 -0
- package/dist/layout-engine/measure/floatingLineClearance.d.ts +24 -0
- package/dist/layout-engine/measure/floatingLineClearance.js +44 -0
- package/dist/layout-engine/measure/inlineObjectMetrics.d.ts +6 -0
- package/dist/layout-engine/measure/inlineObjectMetrics.js +52 -0
- package/dist/layout-engine/measure/justification.d.ts +32 -0
- package/dist/layout-engine/measure/justification.js +83 -0
- package/dist/layout-engine/measure/lineFitting.d.ts +48 -0
- package/dist/layout-engine/measure/lineFitting.js +145 -0
- package/dist/layout-engine/measure/lineTypography.d.ts +44 -0
- package/dist/layout-engine/measure/lineTypography.js +124 -0
- package/dist/layout-engine/measure/measureBlocks.js +2 -1
- package/dist/layout-engine/measure/measureParagraph.d.ts +1 -20
- package/dist/layout-engine/measure/measureParagraph.js +32 -734
- package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +109 -0
- package/dist/layout-engine/measure/paragraphMeasureShared.js +82 -0
- package/dist/layout-engine/measure/paragraphTabs.d.ts +18 -0
- package/dist/layout-engine/measure/paragraphTabs.js +78 -0
- package/dist/layout-engine/paragraphLayout.d.ts +23 -0
- package/dist/layout-engine/paragraphLayout.js +204 -0
- package/dist/layout-engine/sectionLayout.d.ts +45 -0
- package/dist/layout-engine/sectionLayout.js +216 -0
- package/dist/layout-engine/tableLayout.d.ts +17 -0
- package/dist/layout-engine/tableLayout.js +369 -0
- package/dist/layout-engine/textBoxLayout.d.ts +15 -0
- package/dist/layout-engine/textBoxLayout.js +137 -0
- package/dist/layout-painter/renderPage.js +1 -0
- package/dist/paged-layout/sectionBlockWidths.d.ts +2 -1
- package/dist/paged-layout/sectionBlockWidths.js +1 -1
- package/dist/server.d.ts +3 -2
- package/package.json +2 -2
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { setTextBoxGroupId } from "../../layout-engine/textBoxGroup.js";
|
|
2
|
+
import { DEFAULT_TEXTBOX_MARGINS } from "../../layout-engine/types.js";
|
|
3
|
+
import { expectParagraphAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs } from "../../prosemirror/attrs/index.js";
|
|
4
|
+
import { textBoxHostParagraph } from "../../prosemirror/textBoxHostParagraph.js";
|
|
5
|
+
import { normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
|
|
6
|
+
import { convertBorderSpecToLayout } from "./flowBorders.js";
|
|
7
|
+
import { nextBlockId, twipsToPixels } from "./flowConversionShared.js";
|
|
8
|
+
import { countPageBreakRuns, hasSingleLeadingProjectedPageBreak } from "./pageBreakSplitting.js";
|
|
9
|
+
import { convertParagraphAttrs } from "./paragraphAttrs.js";
|
|
10
|
+
import { convertParagraph } from "./paragraphConversion.js";
|
|
11
|
+
import { groupParagraphFrames } from "./paragraphFrames.js";
|
|
12
|
+
import { resolveParagraphMarkFormatting } from "./paragraphMarkFormatting.js";
|
|
13
|
+
import { inlineEffectExtentPx, resolveLinearGradientFill } from "./textBoxFill.js";
|
|
14
|
+
//#region src/layout-bridge/convert/tableConversion.ts
|
|
15
|
+
const TEXT_BOX_ANCHOR_BLOCK_ID = Symbol.for("stll.textBoxAnchorBlockId");
|
|
16
|
+
const DEFAULT_TABLE_CELL_MARGIN_TWIPS = {
|
|
17
|
+
top: 0,
|
|
18
|
+
right: 108,
|
|
19
|
+
bottom: 0,
|
|
20
|
+
left: 108
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Extract cell borders from ProseMirror attributes.
|
|
24
|
+
* Borders are full BorderSpec objects with style/size/color.
|
|
25
|
+
*/
|
|
26
|
+
function extractCellBorders(borders, theme) {
|
|
27
|
+
if (!borders) return;
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const side of [
|
|
30
|
+
"top",
|
|
31
|
+
"bottom",
|
|
32
|
+
"left",
|
|
33
|
+
"right"
|
|
34
|
+
]) {
|
|
35
|
+
const border = borders[side];
|
|
36
|
+
const converted = border ? convertBorderSpecToLayout(border, theme) : void 0;
|
|
37
|
+
if (!converted) {
|
|
38
|
+
result[side] = {
|
|
39
|
+
width: 0,
|
|
40
|
+
style: "none"
|
|
41
|
+
};
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
result[side] = border?.size === 0 ? {
|
|
45
|
+
...converted,
|
|
46
|
+
width: 0
|
|
47
|
+
} : converted;
|
|
48
|
+
}
|
|
49
|
+
for (const side of ["topLeftToBottomRight", "topRightToBottomLeft"]) {
|
|
50
|
+
const border = borders[side];
|
|
51
|
+
const converted = border ? convertBorderSpecToLayout(border, theme) : void 0;
|
|
52
|
+
if (converted) result[side] = converted;
|
|
53
|
+
}
|
|
54
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
55
|
+
}
|
|
56
|
+
function convertTableCell(node, startPos, options, tableCellMargins) {
|
|
57
|
+
const blocks = [];
|
|
58
|
+
let offset = startPos + 1;
|
|
59
|
+
const authoredPageBreakPosition = options.firstPageBreakRunPosition(node);
|
|
60
|
+
const leadingParagraph = node.firstChild?.type.name === "paragraph" && countPageBreakRuns(node) === 1 && options.firstPageBreakRunPosition(node.firstChild) === authoredPageBreakPosition ? node.firstChild : void 0;
|
|
61
|
+
const pageBreaks = [];
|
|
62
|
+
const convertCellChild = (child, childStart) => {
|
|
63
|
+
if (child.type.name === "paragraph") {
|
|
64
|
+
const block = convertParagraph(child, childStart, options, child === leadingParagraph ? pageBreaks : void 0);
|
|
65
|
+
blocks.push(block);
|
|
66
|
+
} else if (child.type.name === "table") blocks.push(convertTable(child, childStart, options));
|
|
67
|
+
else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child, childStart, options));
|
|
68
|
+
else if (child.type.name === "blockSdt") {
|
|
69
|
+
let sdtChildStart = childStart + 1;
|
|
70
|
+
child.forEach((sdtChild) => {
|
|
71
|
+
convertCellChild(sdtChild, sdtChildStart);
|
|
72
|
+
sdtChildStart += sdtChild.nodeSize;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
node.forEach((child) => {
|
|
77
|
+
convertCellChild(child, offset);
|
|
78
|
+
offset += child.nodeSize;
|
|
79
|
+
});
|
|
80
|
+
const trailingBlock = blocks.at(-1);
|
|
81
|
+
if (blocks.at(-2)?.kind === "table" && trailingBlock?.kind === "paragraph" && trailingBlock.runs.every((run) => run.kind === "text" && run.text.length === 0)) trailingBlock.attrs = {
|
|
82
|
+
...trailingBlock.attrs,
|
|
83
|
+
suppressEmptyParagraphHeight: true
|
|
84
|
+
};
|
|
85
|
+
const attrs = expectTableCellAttrs(node);
|
|
86
|
+
if (attrs.hideMark && trailingBlock?.kind === "paragraph" && trailingBlock.runs.every((run) => run.kind === "text" && run.text.length === 0)) trailingBlock.attrs = {
|
|
87
|
+
...trailingBlock.attrs,
|
|
88
|
+
suppressEmptyParagraphHeight: true
|
|
89
|
+
};
|
|
90
|
+
const margins = attrs.margins;
|
|
91
|
+
const resolvePaddingSide = (side, cellTwips, tableTwips) => {
|
|
92
|
+
if (cellTwips !== void 0) return twipsToPixels(cellTwips);
|
|
93
|
+
if (tableTwips !== void 0) return twipsToPixels(tableTwips);
|
|
94
|
+
return twipsToPixels(DEFAULT_TABLE_CELL_MARGIN_TWIPS[side]);
|
|
95
|
+
};
|
|
96
|
+
const padding = {
|
|
97
|
+
top: resolvePaddingSide("top", margins?.top, tableCellMargins?.top),
|
|
98
|
+
right: resolvePaddingSide("right", margins?.right, tableCellMargins?.right),
|
|
99
|
+
bottom: resolvePaddingSide("bottom", margins?.bottom, tableCellMargins?.bottom),
|
|
100
|
+
left: resolvePaddingSide("left", margins?.left, tableCellMargins?.left)
|
|
101
|
+
};
|
|
102
|
+
const cell = {
|
|
103
|
+
id: nextBlockId(),
|
|
104
|
+
blocks: groupParagraphFrames(blocks, nextBlockId),
|
|
105
|
+
colSpan: attrs.colspan,
|
|
106
|
+
rowSpan: attrs.rowspan,
|
|
107
|
+
padding
|
|
108
|
+
};
|
|
109
|
+
if (attrs.width) cell.width = twipsToPixels(attrs.width);
|
|
110
|
+
if (attrs.verticalAlign) cell.verticalAlign = attrs.verticalAlign;
|
|
111
|
+
if (attrs.textDirection) cell.textDirection = attrs.textDirection;
|
|
112
|
+
if (attrs.backgroundColor) cell.background = `#${attrs.backgroundColor}`;
|
|
113
|
+
const cellBorders = extractCellBorders(attrs.borders, options.theme);
|
|
114
|
+
if (cellBorders) cell.borders = cellBorders;
|
|
115
|
+
if (attrs.noWrap) cell.noWrap = true;
|
|
116
|
+
if (authoredPageBreakPosition === void 0 || pageBreaks.length === 0) return { cell };
|
|
117
|
+
const paragraph = blocks.at(0);
|
|
118
|
+
if (paragraph?.kind !== "paragraph" || !hasSingleLeadingProjectedPageBreak(paragraph.runs, pageBreaks)) return { cell };
|
|
119
|
+
return {
|
|
120
|
+
cell,
|
|
121
|
+
breakBefore: "page"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Resolve an `ST_JcTable` placement to the flow engine's logical alignment.
|
|
126
|
+
*
|
|
127
|
+
* `start` and `end` name an edge of the writing direction, not a side of the
|
|
128
|
+
* page, the same distinction `ST_Jc` draws for a paragraph. The flow engine
|
|
129
|
+
* applies `w:bidiVisual` when it resolves that logical alignment to a physical
|
|
130
|
+
* side, so the bridge must not mirror it first.
|
|
131
|
+
*/
|
|
132
|
+
const resolveTablePlacement = (placement) => {
|
|
133
|
+
switch (placement) {
|
|
134
|
+
case "start": return "left";
|
|
135
|
+
case "end": return "right";
|
|
136
|
+
case "left":
|
|
137
|
+
case "center":
|
|
138
|
+
case "right": return placement;
|
|
139
|
+
default: return placement;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
function convertTableRow(node, startPos, options, { cellMargins }) {
|
|
143
|
+
const cells = [];
|
|
144
|
+
let offset = startPos + 1;
|
|
145
|
+
let breakBefore;
|
|
146
|
+
node.forEach((child) => {
|
|
147
|
+
if (child.type.name === "tableCell" || child.type.name === "tableHeader") {
|
|
148
|
+
if (!expectTableCellAttrs(child)._omittedGridSlot) {
|
|
149
|
+
const converted = convertTableCell(child, offset, options, cellMargins);
|
|
150
|
+
if (converted.breakBefore !== void 0) breakBefore = converted.breakBefore;
|
|
151
|
+
cells.push(converted.cell);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
offset += child.nodeSize;
|
|
155
|
+
});
|
|
156
|
+
const attrs = expectTableRowAttrs(node);
|
|
157
|
+
const row = {
|
|
158
|
+
id: nextBlockId(),
|
|
159
|
+
cells
|
|
160
|
+
};
|
|
161
|
+
if (attrs._originalFormatting?.gridBefore) row.gridBefore = attrs._originalFormatting.gridBefore;
|
|
162
|
+
if (attrs._originalFormatting?.gridAfter) row.gridAfter = attrs._originalFormatting.gridAfter;
|
|
163
|
+
if (attrs.height) row.height = twipsToPixels(attrs.height);
|
|
164
|
+
if (attrs.heightRule) row.heightRule = attrs.heightRule;
|
|
165
|
+
if (attrs.isHeader) row.isHeader = attrs.isHeader;
|
|
166
|
+
if (attrs._originalFormatting?.cantSplit) row.cantSplit = true;
|
|
167
|
+
if (breakBefore !== void 0) row.breakBefore = breakBefore;
|
|
168
|
+
if (attrs.hidden) row.hidden = attrs.hidden;
|
|
169
|
+
const effectiveJustification = attrs._originalFormatting?.justification ?? attrs._resolvedJustification;
|
|
170
|
+
if (effectiveJustification) row.justification = resolveTablePlacement(effectiveJustification);
|
|
171
|
+
return row;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convert a table node to a TableBlock.
|
|
175
|
+
*/
|
|
176
|
+
function convertTable(node, startPos, options) {
|
|
177
|
+
const rows = [];
|
|
178
|
+
let offset = startPos + 1;
|
|
179
|
+
const attrs = expectTableAttrs(node);
|
|
180
|
+
const rightToLeft = (attrs._resolvedBidi ?? attrs._originalFormatting?.bidi) === true;
|
|
181
|
+
const rowContext = { ...attrs.cellMargins === void 0 ? {} : { cellMargins: attrs.cellMargins } };
|
|
182
|
+
node.forEach((child) => {
|
|
183
|
+
if (child.type.name === "tableRow") rows.push(convertTableRow(child, offset, options, rowContext));
|
|
184
|
+
offset += child.nodeSize;
|
|
185
|
+
});
|
|
186
|
+
let columnWidths = attrs.columnWidths?.map(twipsToPixels);
|
|
187
|
+
const width = attrs.width;
|
|
188
|
+
const widthType = attrs.widthType;
|
|
189
|
+
if (!columnWidths && rows.length > 0) {
|
|
190
|
+
const cellWidths = rows[0].cells.map((cell) => cell.width);
|
|
191
|
+
if (cellWidths.every((w) => w !== void 0 && w > 0)) columnWidths = cellWidths;
|
|
192
|
+
}
|
|
193
|
+
const authoredJustification = attrs.justification ?? attrs._resolvedJustification;
|
|
194
|
+
const justification = authoredJustification === void 0 ? void 0 : resolveTablePlacement(authoredJustification);
|
|
195
|
+
const originalFormatting = attrs._originalFormatting;
|
|
196
|
+
const effectiveIndent = attrs._resolvedIndent ?? originalFormatting?.indent;
|
|
197
|
+
const indentPx = effectiveIndent?.value !== void 0 && effectiveIndent?.type === "dxa" ? twipsToPixels(effectiveIndent.value) : void 0;
|
|
198
|
+
const dropsAuthoredIndent = effectiveIndent?.value !== void 0 && indentPx === void 0;
|
|
199
|
+
const floating = attrs.floating;
|
|
200
|
+
let floatingPx;
|
|
201
|
+
if (floating) {
|
|
202
|
+
const fp = {};
|
|
203
|
+
if (floating.horzAnchor) fp.horzAnchor = floating.horzAnchor;
|
|
204
|
+
if (floating.vertAnchor) fp.vertAnchor = floating.vertAnchor;
|
|
205
|
+
if (floating.tblpX !== void 0) fp.tblpX = twipsToPixels(floating.tblpX);
|
|
206
|
+
if (floating.tblpXSpec) fp.tblpXSpec = floating.tblpXSpec;
|
|
207
|
+
if (floating.tblpY !== void 0) fp.tblpY = twipsToPixels(floating.tblpY);
|
|
208
|
+
if (floating.tblpYSpec) fp.tblpYSpec = floating.tblpYSpec;
|
|
209
|
+
if (floating.topFromText !== void 0) fp.topFromText = twipsToPixels(floating.topFromText);
|
|
210
|
+
if (floating.bottomFromText !== void 0) fp.bottomFromText = twipsToPixels(floating.bottomFromText);
|
|
211
|
+
if (floating.leftFromText !== void 0) fp.leftFromText = twipsToPixels(floating.leftFromText);
|
|
212
|
+
if (floating.rightFromText !== void 0) fp.rightFromText = twipsToPixels(floating.rightFromText);
|
|
213
|
+
floatingPx = fp;
|
|
214
|
+
}
|
|
215
|
+
const tableBlock = {
|
|
216
|
+
kind: "table",
|
|
217
|
+
id: nextBlockId(),
|
|
218
|
+
rows,
|
|
219
|
+
pmStart: startPos,
|
|
220
|
+
pmEnd: startPos + node.nodeSize
|
|
221
|
+
};
|
|
222
|
+
if (columnWidths) tableBlock.columnWidths = columnWidths;
|
|
223
|
+
if (width !== void 0) tableBlock.width = width;
|
|
224
|
+
if (widthType !== void 0) tableBlock.widthType = widthType;
|
|
225
|
+
if (originalFormatting?.layout !== void 0) tableBlock.layout = originalFormatting.layout;
|
|
226
|
+
if (justification) tableBlock.justification = justification;
|
|
227
|
+
if (indentPx !== void 0) tableBlock.indent = indentPx;
|
|
228
|
+
const cellSpacing = originalFormatting?.cellSpacing;
|
|
229
|
+
if (cellSpacing?.type === "dxa" && cellSpacing.value > 0) tableBlock.cellSpacing = twipsToPixels(cellSpacing.value);
|
|
230
|
+
if (options.tableIndentCompatibility && !dropsAuthoredIndent) tableBlock.indentCompatibility = options.tableIndentCompatibility;
|
|
231
|
+
if (floatingPx) tableBlock.floating = floatingPx;
|
|
232
|
+
if (rightToLeft) tableBlock.bidi = true;
|
|
233
|
+
return tableBlock;
|
|
234
|
+
}
|
|
235
|
+
/** Convert a textBox PM node to a TextBoxBlock. */
|
|
236
|
+
function convertTextBoxNode(node, startPos, opts) {
|
|
237
|
+
const attrs = expectTextBoxAttrs(node);
|
|
238
|
+
const contentBlocks = [];
|
|
239
|
+
node.forEach((child, offset) => {
|
|
240
|
+
const childPos = startPos + 1 + offset;
|
|
241
|
+
if (child.type.name === "paragraph") {
|
|
242
|
+
contentBlocks.push(convertParagraph(child, childPos, opts));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (child.type.name === "table") contentBlocks.push(convertTable(child, childPos, opts));
|
|
246
|
+
});
|
|
247
|
+
const textBox = {
|
|
248
|
+
kind: "textBox",
|
|
249
|
+
id: nextBlockId(),
|
|
250
|
+
width: attrs.width ?? 200,
|
|
251
|
+
margins: {
|
|
252
|
+
top: attrs.marginTop ?? DEFAULT_TEXTBOX_MARGINS.top,
|
|
253
|
+
bottom: attrs.marginBottom ?? DEFAULT_TEXTBOX_MARGINS.bottom,
|
|
254
|
+
left: attrs.marginLeft ?? DEFAULT_TEXTBOX_MARGINS.left,
|
|
255
|
+
right: attrs.marginRight ?? DEFAULT_TEXTBOX_MARGINS.right
|
|
256
|
+
},
|
|
257
|
+
content: contentBlocks,
|
|
258
|
+
pmStart: startPos,
|
|
259
|
+
pmEnd: startPos + node.nodeSize
|
|
260
|
+
};
|
|
261
|
+
const verticalAlign = normalizeShapeTextAnchor(attrs.verticalAlign);
|
|
262
|
+
if (verticalAlign !== void 0) textBox.verticalAlign = verticalAlign;
|
|
263
|
+
if (attrs.height !== void 0) textBox.height = attrs.height;
|
|
264
|
+
if (attrs.autoFit !== void 0) textBox.autoFit = attrs.autoFit;
|
|
265
|
+
if (attrs.textWrap !== void 0) textBox.textWrap = attrs.textWrap;
|
|
266
|
+
if (attrs.fillColor !== void 0) textBox.fillColor = attrs.fillColor;
|
|
267
|
+
else {
|
|
268
|
+
const fillGradient = resolveLinearGradientFill(attrs.gradientFill, opts.theme);
|
|
269
|
+
if (fillGradient !== void 0) textBox.fillGradient = fillGradient;
|
|
270
|
+
}
|
|
271
|
+
if (attrs.outlineWidth !== void 0) textBox.outlineWidth = attrs.outlineWidth;
|
|
272
|
+
if (attrs.outlineColor !== void 0) textBox.outlineColor = attrs.outlineColor;
|
|
273
|
+
if (attrs.outlineStyle !== void 0) textBox.outlineStyle = attrs.outlineStyle;
|
|
274
|
+
if (attrs.transform !== void 0) textBox.transform = attrs.transform;
|
|
275
|
+
if (attrs.displayMode !== void 0) textBox.displayMode = attrs.displayMode;
|
|
276
|
+
if (attrs.cssFloat !== void 0) textBox.cssFloat = attrs.cssFloat;
|
|
277
|
+
if (attrs.wrapType !== void 0) textBox.wrapType = attrs.wrapType;
|
|
278
|
+
if (attrs.wrapText !== void 0) textBox.wrapText = attrs.wrapText;
|
|
279
|
+
if (attrs.distTop !== void 0) textBox.distTop = attrs.distTop;
|
|
280
|
+
if (attrs.distBottom !== void 0) textBox.distBottom = attrs.distBottom;
|
|
281
|
+
if (attrs.distLeft !== void 0) textBox.distLeft = attrs.distLeft;
|
|
282
|
+
if (attrs.distRight !== void 0) textBox.distRight = attrs.distRight;
|
|
283
|
+
if (attrs.position !== void 0) textBox.position = attrs.position;
|
|
284
|
+
const effectExtent = inlineEffectExtentPx(attrs.wrapType, attrs.wrapEffectExtentSlots?.drawing);
|
|
285
|
+
if (effectExtent !== void 0) textBox.effectExtent = effectExtent;
|
|
286
|
+
const host = textBoxHostParagraph(node);
|
|
287
|
+
if (host && attrs.position === void 0 && (attrs.wrapType ?? "inline") === "inline") {
|
|
288
|
+
const hostAttrs = expectParagraphAttrs(host);
|
|
289
|
+
textBox.hostParagraph = convertParagraphAttrs(hostAttrs, {
|
|
290
|
+
theme: opts.theme,
|
|
291
|
+
fontAlternates: opts.fontAlternates,
|
|
292
|
+
listCounterStreams: opts.listCounterStreams,
|
|
293
|
+
defaultTabStopTwips: opts.defaultTabStopTwips,
|
|
294
|
+
paragraphMarkFormatting: () => resolveParagraphMarkFormatting(hostAttrs, opts.styleResolver)
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (attrs._docxGroupId !== void 0) setTextBoxGroupId(textBox, attrs._docxGroupId);
|
|
298
|
+
const anchorBlockId = attrs._docxAnchorId ? opts.textBoxAnchorBlockIds.get(attrs._docxAnchorId) : void 0;
|
|
299
|
+
if (anchorBlockId !== void 0) Reflect.set(textBox, TEXT_BOX_ANCHOR_BLOCK_ID, anchorBlockId);
|
|
300
|
+
return textBox;
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
303
|
+
export { convertTable, convertTextBoxNode };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
import { TextBoxBlock, TextBoxGradientFill } from "../../layout-engine/types.js";
|
|
3
|
+
import { ImagePadding } from "@stll/docx-core/model";
|
|
4
|
+
//#region src/layout-bridge/convert/textBoxFill.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The `wp:effectExtent` of an inline (`wp:inline`) box, in unrounded pixels.
|
|
7
|
+
*
|
|
8
|
+
* An inline object occupies its extent plus the effect extent on every side,
|
|
9
|
+
* so the box itself sits `l`/`t` inside the space the line gives it. On a
|
|
10
|
+
* `wp:anchor` the position offsets already locate the shape's own extent, so
|
|
11
|
+
* the reservation only affects wrapping and is not applied here.
|
|
12
|
+
*/
|
|
13
|
+
declare function inlineEffectExtentPx(wrapType: TextBoxBlock["wrapType"], extent: ImagePadding | undefined): TextBoxBlock["effectExtent"];
|
|
14
|
+
/**
|
|
15
|
+
* A linear `a:gradFill` with its stop colors resolved through the theme. A path
|
|
16
|
+
* gradient (`a:path`) is not painted: nothing here places its focus.
|
|
17
|
+
*/
|
|
18
|
+
declare function resolveLinearGradientFill(fill: document_d_exports.ShapeFill | undefined, theme: document_d_exports.Theme | null | undefined): TextBoxGradientFill | undefined;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { inlineEffectExtentPx, resolveLinearGradientFill };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { resolveColor } from "../../utils/colorResolver.js";
|
|
2
|
+
//#region src/layout-bridge/convert/textBoxFill.ts
|
|
3
|
+
const EMUS_PER_PIXEL = 9525;
|
|
4
|
+
/**
|
|
5
|
+
* The `wp:effectExtent` of an inline (`wp:inline`) box, in unrounded pixels.
|
|
6
|
+
*
|
|
7
|
+
* An inline object occupies its extent plus the effect extent on every side,
|
|
8
|
+
* so the box itself sits `l`/`t` inside the space the line gives it. On a
|
|
9
|
+
* `wp:anchor` the position offsets already locate the shape's own extent, so
|
|
10
|
+
* the reservation only affects wrapping and is not applied here.
|
|
11
|
+
*/
|
|
12
|
+
function inlineEffectExtentPx(wrapType, extent) {
|
|
13
|
+
if (wrapType !== void 0 && wrapType !== "inline" || extent === void 0) return;
|
|
14
|
+
const px = (emu) => Math.max(0, (emu ?? 0) / EMUS_PER_PIXEL);
|
|
15
|
+
const resolved = {
|
|
16
|
+
top: px(extent.top),
|
|
17
|
+
bottom: px(extent.bottom),
|
|
18
|
+
left: px(extent.left),
|
|
19
|
+
right: px(extent.right)
|
|
20
|
+
};
|
|
21
|
+
return resolved.top === 0 && resolved.bottom === 0 && resolved.left === 0 && resolved.right === 0 ? void 0 : resolved;
|
|
22
|
+
}
|
|
23
|
+
const GRADIENT_POSITION_SCALE = 1e5;
|
|
24
|
+
/**
|
|
25
|
+
* A linear `a:gradFill` with its stop colors resolved through the theme. A path
|
|
26
|
+
* gradient (`a:path`) is not painted: nothing here places its focus.
|
|
27
|
+
*/
|
|
28
|
+
function resolveLinearGradientFill(fill, theme) {
|
|
29
|
+
const gradient = fill?.gradient;
|
|
30
|
+
if (gradient === void 0 || gradient.type !== "linear" || gradient.stops.length === 0) return;
|
|
31
|
+
const stops = gradient.stops.map((stop) => ({
|
|
32
|
+
offset: Math.min(1, Math.max(0, stop.position / GRADIENT_POSITION_SCALE)),
|
|
33
|
+
color: resolveColor(stop.color, theme)
|
|
34
|
+
})).toSorted((left, right) => left.offset - right.offset);
|
|
35
|
+
return {
|
|
36
|
+
angle: gradient.angle ?? 0,
|
|
37
|
+
scaled: gradient.scaled ?? false,
|
|
38
|
+
stops
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { inlineEffectExtentPx, resolveLinearGradientFill };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
import { ParagraphAttrs } from "../../prosemirror/schema/nodes.js";
|
|
3
|
+
import { ListMarkerFormatting, RunFormatting } from "../../layout-engine/types.js";
|
|
4
|
+
import { FontAlternates } from "../../fonts/fontAlternates.js";
|
|
5
|
+
//#region src/layout-bridge/convert/textFormattingConversion.d.ts
|
|
6
|
+
type ThemeFontAttributes = Omit<NonNullable<document_d_exports.TextFormatting["fontFamily"]>, "asciiTheme"> & {
|
|
7
|
+
/** The ProseMirror attr reader validates this against the canonical theme values. */
|
|
8
|
+
asciiTheme?: string;
|
|
9
|
+
};
|
|
10
|
+
declare const resolveWesternThemeFont: (fontFamily: ThemeFontAttributes, theme?: document_d_exports.Theme | null) => string | undefined;
|
|
11
|
+
declare const resolveComplexScriptThemeFont: (fontFamily: ThemeFontAttributes, theme?: document_d_exports.Theme | null) => string | undefined;
|
|
12
|
+
declare const resolveEastAsiaThemeFont: (fontFamily: ThemeFontAttributes, theme?: document_d_exports.Theme | null) => string | undefined;
|
|
13
|
+
declare function isAutomaticTextColorValue(color: document_d_exports.ColorValue): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The numbering symbol's typography: the numbering level's `w:rPr` applied
|
|
16
|
+
* over the paragraph mark's run properties (ECMA-376 §17.9.24, §17.3.1.29).
|
|
17
|
+
* Text runs of the paragraph play no part.
|
|
18
|
+
*/
|
|
19
|
+
declare function listMarkerFormattingFor(levelFormatting: document_d_exports.TextFormatting | undefined, paragraphMarkFormatting: document_d_exports.TextFormatting | undefined, theme: document_d_exports.Theme | null | undefined, fontAlternates: FontAlternates | undefined): ListMarkerFormatting | undefined;
|
|
20
|
+
declare function paragraphRunDefaults(pmAttrs: ParagraphAttrs, theme?: document_d_exports.Theme | null, fontAlternates?: FontAlternates): RunFormatting;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { isAutomaticTextColorValue, listMarkerFormattingFor, paragraphRunDefaults, resolveComplexScriptThemeFont, resolveEastAsiaThemeFont, resolveWesternThemeFont };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { getFontAlternate } from "../../fonts/fontAlternates.js";
|
|
2
|
+
import { resolveColor, resolveHighlightToCss } from "../../utils/colorResolver.js";
|
|
3
|
+
import { resolveThemeFont } from "../../utils/fontResolver.js";
|
|
4
|
+
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
5
|
+
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
6
|
+
import { halfPointsToPixels, halfPointsToPoints } from "../../utils/units.js";
|
|
7
|
+
import { twipsToPixels } from "./flowConversionShared.js";
|
|
8
|
+
//#region src/layout-bridge/convert/textFormattingConversion.ts
|
|
9
|
+
/**
|
|
10
|
+
* Converts document-model TextFormatting (style, paragraph-mark, and list
|
|
11
|
+
* marker run properties) to layout RunFormatting, including theme-font
|
|
12
|
+
* resolution per script slot.
|
|
13
|
+
*/
|
|
14
|
+
const resolveWesternThemeFont = (fontFamily, theme) => {
|
|
15
|
+
const themeRef = fontFamily.asciiTheme ?? fontFamily.hAnsiTheme;
|
|
16
|
+
return (themeRef ? resolveThemeFont(themeRef, theme?.fontScheme) : null) ?? fontFamily.ascii ?? fontFamily.hAnsi ?? void 0;
|
|
17
|
+
};
|
|
18
|
+
const resolveComplexScriptThemeFont = (fontFamily, theme) => {
|
|
19
|
+
return (fontFamily.csTheme ? resolveThemeFont(fontFamily.csTheme, theme?.fontScheme) : null) ?? fontFamily.cs ?? void 0;
|
|
20
|
+
};
|
|
21
|
+
const resolveEastAsiaThemeFont = (fontFamily, theme) => {
|
|
22
|
+
return (fontFamily.eastAsiaTheme ? resolveThemeFont(fontFamily.eastAsiaTheme, theme?.fontScheme) : null) ?? fontFamily.eastAsia ?? void 0;
|
|
23
|
+
};
|
|
24
|
+
function isAutomaticTextColorValue(color) {
|
|
25
|
+
const rgb = color.rgb?.trim().toLowerCase();
|
|
26
|
+
return color.auto === true || rgb === "auto" || !rgb && !color.themeColor;
|
|
27
|
+
}
|
|
28
|
+
function textFormattingToRunFormatting(defaultTextFormatting, theme, fontAlternates) {
|
|
29
|
+
if (!defaultTextFormatting) return {};
|
|
30
|
+
const result = {};
|
|
31
|
+
const fontFamily = defaultTextFormatting.fontFamily ? resolveWesternThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
|
|
32
|
+
if (fontFamily) {
|
|
33
|
+
result.fontFamily = fontFamily;
|
|
34
|
+
const alternate = getFontAlternate(fontFamily, fontAlternates);
|
|
35
|
+
if (alternate) result.alternateFontFamily = alternate;
|
|
36
|
+
}
|
|
37
|
+
const eastAsiaFontFamily = defaultTextFormatting.fontFamily ? resolveEastAsiaThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
|
|
38
|
+
if (eastAsiaFontFamily) {
|
|
39
|
+
result.eastAsiaFontFamily = eastAsiaFontFamily;
|
|
40
|
+
const alternate = getFontAlternate(eastAsiaFontFamily, fontAlternates);
|
|
41
|
+
if (alternate) result.eastAsiaAlternateFontFamily = alternate;
|
|
42
|
+
}
|
|
43
|
+
if (defaultTextFormatting.fontFamily?.hint) result.eastAsiaHint = defaultTextFormatting.fontFamily.hint === "eastAsia";
|
|
44
|
+
const complexScriptFontFamily = defaultTextFormatting.fontFamily ? resolveComplexScriptThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
|
|
45
|
+
if (complexScriptFontFamily) {
|
|
46
|
+
result.complexScriptFontFamily = complexScriptFontFamily;
|
|
47
|
+
const alternate = getFontAlternate(complexScriptFontFamily, fontAlternates);
|
|
48
|
+
if (alternate) result.complexScriptAlternateFontFamily = alternate;
|
|
49
|
+
}
|
|
50
|
+
if (defaultTextFormatting.language) result.language = { ...defaultTextFormatting.language };
|
|
51
|
+
if (defaultTextFormatting.fontSize !== void 0) result.fontSize = defaultTextFormatting.fontSize / 2;
|
|
52
|
+
if (defaultTextFormatting.fontSizeCs !== void 0) result.complexScriptFontSize = defaultTextFormatting.fontSizeCs / 2;
|
|
53
|
+
if (defaultTextFormatting.bold !== void 0) result.bold = defaultTextFormatting.bold;
|
|
54
|
+
if (defaultTextFormatting.boldCs !== void 0) result.complexScriptBold = defaultTextFormatting.boldCs;
|
|
55
|
+
if (defaultTextFormatting.italic !== void 0) result.italic = defaultTextFormatting.italic;
|
|
56
|
+
if (defaultTextFormatting.italicCs !== void 0) result.complexScriptItalic = defaultTextFormatting.italicCs;
|
|
57
|
+
if (defaultTextFormatting.rtl !== void 0) result.rtl = defaultTextFormatting.rtl;
|
|
58
|
+
if (defaultTextFormatting.cs !== void 0) result.forceComplexScript = defaultTextFormatting.cs;
|
|
59
|
+
if (defaultTextFormatting.underline && defaultTextFormatting.underline.style !== "none") {
|
|
60
|
+
result.underline = { style: defaultTextFormatting.underline.style };
|
|
61
|
+
if (defaultTextFormatting.underline.color) result.underline.color = resolveColor(defaultTextFormatting.underline.color, theme);
|
|
62
|
+
}
|
|
63
|
+
if (defaultTextFormatting.strike !== void 0) result.strike = defaultTextFormatting.strike;
|
|
64
|
+
if (defaultTextFormatting.color && !isAutomaticTextColorValue(defaultTextFormatting.color)) {
|
|
65
|
+
result.color = resolveColor(defaultTextFormatting.color, theme);
|
|
66
|
+
result.textColorSource = "paragraphDefault";
|
|
67
|
+
}
|
|
68
|
+
if (defaultTextFormatting.highlight) {
|
|
69
|
+
const highlight = resolveHighlightToCss(defaultTextFormatting.highlight);
|
|
70
|
+
if (highlight) result.highlight = highlight;
|
|
71
|
+
}
|
|
72
|
+
if (defaultTextFormatting.vertAlign === "superscript") result.superscript = true;
|
|
73
|
+
if (defaultTextFormatting.vertAlign === "subscript") result.subscript = true;
|
|
74
|
+
if (defaultTextFormatting.allCaps !== void 0) result.allCaps = defaultTextFormatting.allCaps;
|
|
75
|
+
if (defaultTextFormatting.smallCaps !== void 0) result.smallCaps = defaultTextFormatting.smallCaps;
|
|
76
|
+
if (defaultTextFormatting.spacing !== void 0 && defaultTextFormatting.spacing !== 0) result.letterSpacing = twipsToPixels(defaultTextFormatting.spacing);
|
|
77
|
+
if (defaultTextFormatting.position !== void 0 && defaultTextFormatting.position !== 0) result.positionPx = halfPointsToPixels(defaultTextFormatting.position);
|
|
78
|
+
const horizontalScale = normalizeHorizontalScalePercent(defaultTextFormatting.scale);
|
|
79
|
+
if (horizontalScale !== void 0 && horizontalScale !== 100) result.horizontalScale = horizontalScale;
|
|
80
|
+
if (defaultTextFormatting.kerning !== void 0 && defaultTextFormatting.kerning > 0) result.kerningMinPt = halfPointsToPoints(defaultTextFormatting.kerning);
|
|
81
|
+
if (defaultTextFormatting.emboss !== void 0) result.emboss = defaultTextFormatting.emboss;
|
|
82
|
+
if (defaultTextFormatting.imprint !== void 0) result.imprint = defaultTextFormatting.imprint;
|
|
83
|
+
if (defaultTextFormatting.shadow !== void 0) result.textShadow = defaultTextFormatting.shadow;
|
|
84
|
+
if (defaultTextFormatting.outline !== void 0) result.textOutline = defaultTextFormatting.outline;
|
|
85
|
+
if (defaultTextFormatting.emphasisMark && defaultTextFormatting.emphasisMark !== "none") result.emphasisMark = defaultTextFormatting.emphasisMark;
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
const LIST_MARKER_FORMATTING_KEYS = [
|
|
89
|
+
"fontFamily",
|
|
90
|
+
"alternateFontFamily",
|
|
91
|
+
"eastAsiaFontFamily",
|
|
92
|
+
"eastAsiaAlternateFontFamily",
|
|
93
|
+
"complexScriptFontFamily",
|
|
94
|
+
"complexScriptAlternateFontFamily",
|
|
95
|
+
"fontSize",
|
|
96
|
+
"complexScriptFontSize",
|
|
97
|
+
"bold",
|
|
98
|
+
"complexScriptBold",
|
|
99
|
+
"italic",
|
|
100
|
+
"complexScriptItalic",
|
|
101
|
+
"rtl",
|
|
102
|
+
"forceComplexScript",
|
|
103
|
+
"color"
|
|
104
|
+
];
|
|
105
|
+
/**
|
|
106
|
+
* The numbering symbol's typography: the numbering level's `w:rPr` applied
|
|
107
|
+
* over the paragraph mark's run properties (ECMA-376 §17.9.24, §17.3.1.29).
|
|
108
|
+
* Text runs of the paragraph play no part.
|
|
109
|
+
*/
|
|
110
|
+
function listMarkerFormattingFor(levelFormatting, paragraphMarkFormatting, theme, fontAlternates) {
|
|
111
|
+
const runFormatting = textFormattingToRunFormatting(mergeTextFormatting(paragraphMarkFormatting, levelFormatting), theme, fontAlternates);
|
|
112
|
+
const formatting = {};
|
|
113
|
+
for (const key of LIST_MARKER_FORMATTING_KEYS) if (runFormatting[key] !== void 0) Reflect.set(formatting, key, runFormatting[key]);
|
|
114
|
+
return Object.keys(formatting).length > 0 ? formatting : void 0;
|
|
115
|
+
}
|
|
116
|
+
function paragraphRunDefaults(pmAttrs, theme, fontAlternates) {
|
|
117
|
+
return textFormattingToRunFormatting(pmAttrs.defaultTextFormatting, theme, fontAlternates);
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { isAutomaticTextColorValue, listMarkerFormattingFor, paragraphRunDefaults, resolveComplexScriptThemeFont, resolveEastAsiaThemeFont, resolveWesternThemeFont };
|
|
@@ -1,102 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BorderStyle, FlowBlock, ParagraphAttrs, TableBlock } from "../../layout-engine/types.js";
|
|
3
|
-
import { FontAlternates } from "../../fonts/fontAlternates.js";
|
|
1
|
+
import { FlowBlock } from "../../layout-engine/types.js";
|
|
4
2
|
import { formatCounter, resolveListTemplate } from "../../prosemirror/listMarker.js";
|
|
3
|
+
import { ToFlowBlocksOptions, resetBlockIdCounter } from "./flowConversionShared.js";
|
|
4
|
+
import { collectNoteRefs, isNoteReferenceMarkXml } from "./noteReferences.js";
|
|
5
|
+
import { convertBorderSpecToLayout } from "./flowBorders.js";
|
|
5
6
|
import { Node } from "prosemirror-model";
|
|
6
7
|
//#region src/layout-bridge/convert/toFlowBlocks.d.ts
|
|
7
|
-
/**
|
|
8
|
-
* Options for the conversion.
|
|
9
|
-
*/
|
|
10
|
-
type ToFlowBlocksOptions = {
|
|
11
|
-
/** Default font family. */
|
|
12
|
-
defaultFont?: string;
|
|
13
|
-
/** Default font size in points. */
|
|
14
|
-
defaultSize?: number;
|
|
15
|
-
/** Theme for resolving theme colors. */
|
|
16
|
-
theme?: document_d_exports.Theme | null;
|
|
17
|
-
/** Document styles used to resolve character-style toggles without per-run copies. */
|
|
18
|
-
styles?: document_d_exports.StyleDefinitions;
|
|
19
|
-
/** Document-scoped OOXML primary-font to `w:altName` lookup. */
|
|
20
|
-
fontAlternates?: FontAlternates;
|
|
21
|
-
/** Page content height in pixels (pageHeight - marginTop - marginBottom). Images taller than this are scaled down to fit. */
|
|
22
|
-
pageContentHeight?: number;
|
|
23
|
-
/** Whether a trailing page break moves its paragraph mark to the next page. */
|
|
24
|
-
splitPageBreakAndParagraphMark?: boolean;
|
|
25
|
-
/** Shared list counters for nested containers. */
|
|
26
|
-
listCounters?: Map<number, number[]>;
|
|
27
|
-
/** Latest concrete counters by abstract numbering definition. */
|
|
28
|
-
listAbstractCounters?: Map<number, number[]>;
|
|
29
|
-
/** Shared startOverride state for nested containers. */
|
|
30
|
-
listSeenNumIds?: Set<string>;
|
|
31
|
-
/**
|
|
32
|
-
* Parallel counter state for the "original" (pre-revision) document, used to
|
|
33
|
-
* number tracked-deletion list items. Word numbers inserted and deleted list
|
|
34
|
-
* runs as if they never coexist: insertions get final-document numbering,
|
|
35
|
-
* deletions keep their original numbering. Without a separate stream a deleted
|
|
36
|
-
* item continues the counter of the inserted item before it (a, b → c, d, e
|
|
37
|
-
* instead of a, b and a, b, c). Normal items advance both streams.
|
|
38
|
-
*/
|
|
39
|
-
originalListCounters?: Map<number, number[]>;
|
|
40
|
-
/** Latest concrete original-stream counters by abstract numbering definition. */
|
|
41
|
-
originalListAbstractCounters?: Map<number, number[]>;
|
|
42
|
-
/** Original-stream startOverride state. */
|
|
43
|
-
originalListSeenNumIds?: Set<string>;
|
|
44
|
-
/**
|
|
45
|
-
* Document-wide `w:defaultTabStop` (§17.6.13) in twips. Stamped onto
|
|
46
|
-
* every paragraph block so paragraph-local layout helpers (list marker
|
|
47
|
-
* tab-stop math) can read it without taking a `Document` reference.
|
|
48
|
-
* Defaults to the OOXML 720-twip value when absent.
|
|
49
|
-
*/
|
|
50
|
-
defaultTabStopTwips?: number;
|
|
51
|
-
/** Document-wide custom Word line-breaking settings. */
|
|
52
|
-
lineBreakRules?: {
|
|
53
|
-
noLineBreaksBefore?: {
|
|
54
|
-
language?: string;
|
|
55
|
-
characters: string;
|
|
56
|
-
};
|
|
57
|
-
noLineBreaksAfter?: {
|
|
58
|
-
language?: string;
|
|
59
|
-
characters: string;
|
|
60
|
-
};
|
|
61
|
-
useLegacyEthiopicAmharicRules?: boolean;
|
|
62
|
-
};
|
|
63
|
-
/** Document-generation policy for justified line fitting. */
|
|
64
|
-
justificationCompatibility?: NonNullable<ParagraphAttrs["justificationCompatibility"]>;
|
|
65
|
-
/** Document-generation policy for where `w:tblInd` is measured from. */
|
|
66
|
-
tableIndentCompatibility?: NonNullable<TableBlock["indentCompatibility"]>;
|
|
67
|
-
/**
|
|
68
|
-
* When set, every table-cell anchor lays out inside its cell regardless of
|
|
69
|
-
* an authored `wp:anchor/@layoutInCell="0"`. Compatibility mode 15 and
|
|
70
|
-
* above ignore that opt-out; see `resolveAnchorLayoutInCellCompatibility`.
|
|
71
|
-
*/
|
|
72
|
-
forceAnchorLayoutInCell?: boolean;
|
|
73
|
-
/** Document-wide automatic hyphenation policy. */
|
|
74
|
-
automaticHyphenation?: NonNullable<ParagraphAttrs["automaticHyphenation"]>;
|
|
75
|
-
/** Line pitch for the final body section, whose properties live outside the PM body. */
|
|
76
|
-
finalSectionDocumentGridLinePitchTwips?: number;
|
|
77
|
-
/**
|
|
78
|
-
* The number a note story's `w:footnoteRef`/`w:endnoteRef` marks show. The
|
|
79
|
-
* mark stands for its note's reference number and shows it where it sits
|
|
80
|
-
* among the story's runs, in that run's formatting.
|
|
81
|
-
*/
|
|
82
|
-
noteReferenceMarkText?: string;
|
|
83
|
-
/**
|
|
84
|
-
* Endnotes laid out after the body's last block (`w:pos="docEnd"`). A body
|
|
85
|
-
* that references one ends in its endnote area, so its final paragraph is no
|
|
86
|
-
* longer the document's last and keeps its height.
|
|
87
|
-
*/
|
|
88
|
-
trailingEndnoteIds?: ReadonlySet<number>;
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Runs with `idKey` set, in document order: the note references a block list
|
|
92
|
-
* makes, through table cells (and tables within cells) and text boxes.
|
|
93
|
-
*/
|
|
94
|
-
declare function collectNoteRefs(blocks: readonly FlowBlock[], idKey: "footnoteRefId" | "endnoteRefId"): {
|
|
95
|
-
noteId: number;
|
|
96
|
-
pmPos: number;
|
|
97
|
-
}[];
|
|
98
|
-
/** Whether captured run-child markup is a note story's `w:footnoteRef`/`w:endnoteRef`. */
|
|
99
|
-
declare function isNoteReferenceMarkXml(xml: string): boolean;
|
|
100
8
|
/**
|
|
101
9
|
* Word's layout fallback when an imported OOXML style hierarchy never supplies
|
|
102
10
|
* `w:sz`. ECMA-376 deliberately leaves that terminal fallback to the consumer;
|
|
@@ -105,22 +13,6 @@ declare function isNoteReferenceMarkXml(xml: string): boolean;
|
|
|
105
13
|
* default.
|
|
106
14
|
*/
|
|
107
15
|
declare const WORD_UNSPECIFIED_FONT_SIZE = 10;
|
|
108
|
-
/**
|
|
109
|
-
* Reset the block ID counter (useful for testing).
|
|
110
|
-
*/
|
|
111
|
-
declare function resetBlockIdCounter(): void;
|
|
112
|
-
/** A parsed border, or the same shape read off ProseMirror attributes. */
|
|
113
|
-
type ConvertibleBorder = {
|
|
114
|
-
style?: document_d_exports.BorderStyleValue;
|
|
115
|
-
size?: number;
|
|
116
|
-
space?: number;
|
|
117
|
-
color?: document_d_exports.ColorValue;
|
|
118
|
-
};
|
|
119
|
-
/**
|
|
120
|
-
* Convert an OOXML BorderSpec to a layout-engine BorderStyle.
|
|
121
|
-
* Shared by paragraph borders, cell borders, and header/footer borders.
|
|
122
|
-
*/
|
|
123
|
-
declare function convertBorderSpecToLayout(border: ConvertibleBorder, theme?: document_d_exports.Theme | null): BorderStyle | undefined;
|
|
124
16
|
/**
|
|
125
17
|
* Convert a ProseMirror document to FlowBlock array.
|
|
126
18
|
*
|
|
@@ -129,4 +21,4 @@ declare function convertBorderSpecToLayout(border: ConvertibleBorder, theme?: do
|
|
|
129
21
|
*/
|
|
130
22
|
declare function toFlowBlocks(doc: Node, options?: ToFlowBlocksOptions): FlowBlock[];
|
|
131
23
|
//#endregion
|
|
132
|
-
export { ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|
|
24
|
+
export { type ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|