@stll/folio-core 0.7.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/blockRange.d.ts +13 -2
- package/dist/ai-edits/blockRange.js +23 -2
- package/dist/ai-edits/headless.d.ts +31 -4
- package/dist/ai-edits/headless.js +148 -35
- package/dist/ai-edits/index.d.ts +6 -4
- package/dist/ai-edits/index.js +4 -1
- package/dist/ai-edits/scoped-reading.d.ts +9 -0
- package/dist/ai-edits/scoped-reading.js +60 -0
- package/dist/ai-edits/snapshot.js +53 -7
- package/dist/ai-edits/types.d.ts +46 -3
- package/dist/compat/eigenpal.d.ts +8 -3
- package/dist/compat/eigenpal.js +7 -2
- package/dist/controller/fontReadiness.d.ts +29 -0
- package/dist/controller/fontReadiness.js +139 -0
- package/dist/controller/latestRequestGate.d.ts +13 -0
- package/dist/controller/latestRequestGate.js +16 -0
- package/dist/controller/layoutPipeline.js +88 -10
- package/dist/document-operations.d.ts +10 -3
- package/dist/document-operations.js +29 -14
- package/dist/docx/blockContentParser.js +53 -10
- package/dist/docx/commentParser.js +1 -1
- package/dist/docx/compatibility.d.ts +30 -2
- package/dist/docx/compatibility.js +118 -39
- package/dist/docx/conformance.d.ts +6 -0
- package/dist/docx/conformance.js +18 -0
- 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/ensureParaIds.d.ts +29 -0
- package/dist/docx/ensureParaIds.js +423 -0
- 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 +2 -0
- package/dist/docx/paragraphParser.js +21 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +141 -2
- package/dist/docx/parser.d.ts +1 -1
- package/dist/docx/parser.js +14 -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/selectiveXmlPatch.d.ts +10 -1
- package/dist/docx/selectiveXmlPatch.js +1 -1
- 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 +8 -0
- package/dist/docx/serializer/runSerializer.js +14 -2
- 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 +29 -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 +19 -1
- package/dist/docx/textBoxParser.js +6 -1
- package/dist/docx/vmlImageParser.js +146 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
- package/dist/i18n/messages/catalogs.gen.js +5910 -5910
- package/dist/index.d.ts +8 -3
- package/dist/index.js +7 -2
- 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 +22 -3
- package/dist/layout-bridge/convert/paragraphFrames.d.ts +7 -0
- package/dist/layout-bridge/convert/paragraphFrames.js +136 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +93 -17
- package/dist/layout-bridge/engine/hitTest.js +2 -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 +2 -1
- package/dist/layout-engine/headerFooterRefs.d.ts +7 -0
- package/dist/layout-engine/headerFooterRefs.js +40 -0
- package/dist/layout-engine/index.d.ts +3 -2
- package/dist/layout-engine/index.js +68 -106
- 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 +4 -1
- package/dist/layout-engine/measure/listMarkerWidth.js +33 -8
- package/dist/layout-engine/measure/measureBlocks.d.ts +4 -2
- package/dist/layout-engine/measure/measureBlocks.js +138 -86
- 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 +346 -74
- 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.d.ts +15 -0
- package/dist/layout-engine/measure/tableCellGrid.js +62 -0
- package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +18 -0
- package/dist/layout-engine/measure/textBoxParagraphLayout.js +32 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
- package/dist/layout-engine/paginator.d.ts +2 -1
- package/dist/layout-engine/paginator.js +7 -6
- package/dist/layout-engine/paragraphFrame.d.ts +22 -0
- package/dist/layout-engine/paragraphFrame.js +17 -0
- package/dist/layout-engine/paragraphSequence.d.ts +7 -0
- package/dist/layout-engine/paragraphSequence.js +25 -0
- package/dist/layout-engine/paragraphSpacing.d.ts +17 -0
- package/dist/layout-engine/paragraphSpacing.js +30 -0
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +63 -0
- package/dist/layout-engine/renderedBreakReconciliation.js +86 -0
- package/dist/layout-engine/tableRowBreak.d.ts +5 -2
- package/dist/layout-engine/tableRowBreak.js +62 -29
- package/dist/layout-engine/types.d.ts +54 -12
- package/dist/layout-engine/types.js +15 -2
- 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 +15 -101
- package/dist/layout-painter/renderParagraph.js +45 -26
- package/dist/layout-painter/renderTable.d.ts +2 -0
- package/dist/layout-painter/renderTable.js +257 -47
- package/dist/layout-painter/renderTextBox.js +17 -7
- package/dist/managers/DocumentLoaderManager.d.ts +1 -1
- package/dist/managers/DocumentLoaderManager.js +2 -2
- package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
- package/dist/paged-layout/sectionBlockWidths.js +9 -0
- package/dist/paged-layout/sectionGeometry.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +32 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +35 -18
- package/dist/prosemirror/conversion/toProseDoc.js +73 -37
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +8 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +2 -0
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +68 -16
- 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/extensions/nodes/TextBoxExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
- 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 +16 -12
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -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 +9 -4
- package/dist/server.js +7 -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/types/index.d.ts +2 -1
- package/dist/utils/createDocument.d.ts +12 -2
- package/dist/utils/createDocument.js +55 -36
- package/dist/utils/fontResolver.js +6 -6
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/hexId.d.ts +8 -1
- package/dist/utils/hexId.js +11 -3
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
- package/dist/utils/paragraphFormattingMerge.js +14 -4
- package/package.json +5 -1
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { emuToPixels } from "../utils/units.js";
|
|
2
2
|
import { measuredLineAdvance } from "./lineFlow.js";
|
|
3
|
-
import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, tableColumnsArePinned } from "./types.js";
|
|
3
|
+
import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, tableColumnsArePinned } from "./types.js";
|
|
4
|
+
import { getParagraphSpacingAfter, getParagraphSpacingBefore } from "./paragraphSpacing.js";
|
|
4
5
|
import { calculateChainHeight, computeKeepNextChains, getMidChainIndices, hasKeepLines, hasPageBreakBefore } from "./keep-together.js";
|
|
6
|
+
import { continuesNumberedSequence } from "./paragraphSequence.js";
|
|
5
7
|
import { createPaginator } from "./paginator.js";
|
|
6
8
|
import { getParagraphFragmentPmRange } from "./paragraphFragmentRange.js";
|
|
7
|
-
import {
|
|
9
|
+
import { INITIAL_RENDERED_BREAK_STATE, reconcileAfterBlock, reconcileBreakBeforeBlock, recordReflowBoundary } from "./renderedBreakReconciliation.js";
|
|
10
|
+
import { buildTableRowBreakInfo, getRowContinuationSkip, snapRowBreak } from "./tableRowBreak.js";
|
|
8
11
|
import { bandFragmentX, bandTopContentY, isPageFrameRelativeAnchor } from "./textBoxFlow.js";
|
|
12
|
+
import { resolveSectionHeaderFooterRefs } from "./headerFooterRefs.js";
|
|
9
13
|
import { applyPendingToActive, createInitialSectionState, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, scheduleSectionBreak } from "./section-breaks.js";
|
|
10
14
|
import { assertExhaustiveFlowBlock, findPageIndexContainingPmPos } from "./pmPageIndex.js";
|
|
11
15
|
import { panic } from "better-result";
|
|
@@ -19,6 +23,7 @@ const DEFAULT_COLUMNS = {
|
|
|
19
23
|
count: 1,
|
|
20
24
|
gap: 0
|
|
21
25
|
};
|
|
26
|
+
const DEFAULT_SECTION_BREAK_TYPE = "nextPage";
|
|
22
27
|
function collectSectionConfigs(blocks, initialConfig, finalConfig) {
|
|
23
28
|
const configs = [];
|
|
24
29
|
const breakIndices = [];
|
|
@@ -42,63 +47,6 @@ function collectSectionConfigs(blocks, initialConfig, finalConfig) {
|
|
|
42
47
|
breakIndices
|
|
43
48
|
};
|
|
44
49
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Whether a paragraph block has no visible content (no runs, or a single
|
|
47
|
-
* empty text run).
|
|
48
|
-
*/
|
|
49
|
-
function isEmptyParagraph(block) {
|
|
50
|
-
if (block.runs.length === 0) return true;
|
|
51
|
-
if (block.runs.length !== 1) return false;
|
|
52
|
-
const r = block.runs[0];
|
|
53
|
-
return r?.kind === "text" && r.text === "";
|
|
54
|
-
}
|
|
55
|
-
function isPaginationEmptyParagraph(block) {
|
|
56
|
-
return block.runs.every((run) => {
|
|
57
|
-
if (run.kind === "text") return run.text.trim().length === 0;
|
|
58
|
-
return run.kind === "tab" || run.kind === "lineBreak";
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function pageHasVisibleBodyContent(page, blocksById) {
|
|
62
|
-
for (const fragment of page.fragments) {
|
|
63
|
-
if (fragment.kind !== "paragraph") return true;
|
|
64
|
-
const block = blocksById.get(String(fragment.blockId));
|
|
65
|
-
if (block?.kind !== "paragraph" || !isPaginationEmptyParagraph(block)) return true;
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
function continuesNumberedSequence(previous, current) {
|
|
70
|
-
if (previous?.kind !== "paragraph" || current.kind !== "paragraph") return false;
|
|
71
|
-
const previousNumPr = previous.attrs?.numPr;
|
|
72
|
-
const currentNumPr = current.attrs?.numPr;
|
|
73
|
-
if (previousNumPr?.numId === void 0 || currentNumPr?.numId === void 0) return false;
|
|
74
|
-
return previousNumPr.numId === currentNumPr.numId && previousNumPr.ilvl === currentNumPr.ilvl;
|
|
75
|
-
}
|
|
76
|
-
function pageStartsWithPreviousParagraphContinuation(page, previousBlock) {
|
|
77
|
-
if (previousBlock?.kind !== "paragraph") return false;
|
|
78
|
-
return page.fragments.some((fragment) => fragment.kind === "paragraph" && String(fragment.blockId) === String(previousBlock.id) && fragment.continuesFromPrev === true);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get spacing before a paragraph block. Empty paragraphs whose
|
|
82
|
-
* `before` came only from the implicit default paragraph style collapse to
|
|
83
|
-
* zero. Reference layout keeps inherited spacing when the empty paragraph itself is
|
|
84
|
-
* authored through direct `w:pPr` formatting or an explicit `w:pStyle`.
|
|
85
|
-
*/
|
|
86
|
-
function getSpacingBefore(block) {
|
|
87
|
-
const value = block.attrs?.spacing?.before ?? 0;
|
|
88
|
-
if (value === 0) return 0;
|
|
89
|
-
if (isEmptyParagraph(block) && !block.attrs?.styleId && !block.attrs?.hasDirectParagraphFormatting && !block.attrs?.spacingExplicit?.before) return 0;
|
|
90
|
-
return value;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Get spacing after a paragraph block. Same implicit-default-style collapse
|
|
94
|
-
* rule as `getSpacingBefore`.
|
|
95
|
-
*/
|
|
96
|
-
function getSpacingAfter(block) {
|
|
97
|
-
const value = block.attrs?.spacing?.after ?? 0;
|
|
98
|
-
if (value === 0) return 0;
|
|
99
|
-
if (isEmptyParagraph(block) && !block.attrs?.styleId && !block.attrs?.hasDirectParagraphFormatting && !block.attrs?.spacingExplicit?.after) return 0;
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
50
|
function balancedParagraphSectionHeight({ blocks, measures, startIndex, endIndex, incomingSpacing, columnCount, availableHeight }) {
|
|
103
51
|
if (columnCount <= 1 || startIndex >= endIndex || availableHeight <= 0) return;
|
|
104
52
|
const lineUnits = [];
|
|
@@ -110,7 +58,7 @@ function balancedParagraphSectionHeight({ blocks, measures, startIndex, endIndex
|
|
|
110
58
|
const measure = measures[index];
|
|
111
59
|
if (block?.kind !== "paragraph" || measure?.kind !== "paragraph") return;
|
|
112
60
|
if (block.attrs?.keepNext === true || block.attrs?.keepLines === true || block.runs.some((run) => run.kind === "text" && run.footnoteRefId !== void 0)) return;
|
|
113
|
-
const leadingSpacing = Math.max(
|
|
61
|
+
const leadingSpacing = Math.max(getParagraphSpacingBefore(block), trailingSpacing);
|
|
114
62
|
if (measure.lines.length === 0) {
|
|
115
63
|
if (leadingSpacing > 0) {
|
|
116
64
|
lineUnits.push(leadingSpacing);
|
|
@@ -127,7 +75,7 @@ function balancedParagraphSectionHeight({ blocks, measures, startIndex, endIndex
|
|
|
127
75
|
tallestUnit = Math.max(tallestUnit, unitHeight);
|
|
128
76
|
}
|
|
129
77
|
if (tallestUnit > availableHeight || totalHeight > availableHeight * columnCount) return;
|
|
130
|
-
trailingSpacing =
|
|
78
|
+
trailingSpacing = getParagraphSpacingAfter(block);
|
|
131
79
|
}
|
|
132
80
|
if (totalHeight <= 0) return;
|
|
133
81
|
const columnsNeeded = (targetHeight) => {
|
|
@@ -236,13 +184,14 @@ function layoutDocument(blocks, measures, options) {
|
|
|
236
184
|
const finalColumns = options.finalColumns ?? options.columns;
|
|
237
185
|
if (finalColumns !== void 0) finalConfig.columns = finalColumns;
|
|
238
186
|
const { configs: sectionConfigs, breakIndices } = collectSectionConfigs(blocks, bodyConfig, finalConfig);
|
|
239
|
-
const sectionBreakTypes =
|
|
187
|
+
const sectionBreakTypes = breakIndices.map((index) => blocks[index].type);
|
|
240
188
|
const initialConfig = sectionConfigs.at(0) ?? bodyConfig;
|
|
241
189
|
const paginator = createPaginator({
|
|
242
190
|
pageSize: initialConfig.pageSize,
|
|
243
191
|
margins: initialConfig.margins,
|
|
244
192
|
...options.mirrorMargins === true ? { mirrorMargins: true } : {},
|
|
245
193
|
...options.firstPageMargins !== void 0 ? { firstPageMargins: options.firstPageMargins } : {},
|
|
194
|
+
...options.sectionEvenPageMargins !== void 0 ? { sectionEvenPageMargins: options.sectionEvenPageMargins } : {},
|
|
246
195
|
columns: initialConfig.columns ?? DEFAULT_COLUMNS,
|
|
247
196
|
...options.footnoteReservedHeights !== void 0 ? { footnoteReservedHeights: options.footnoteReservedHeights } : {},
|
|
248
197
|
...options.sectionHeaderFooterRefs !== void 0 ? { sectionHeaderFooterRefs: options.sectionHeaderFooterRefs } : {}
|
|
@@ -257,28 +206,41 @@ function layoutDocument(blocks, measures, options) {
|
|
|
257
206
|
let activeSectionMarginTop = initialConfig.margins.top;
|
|
258
207
|
let activeSectionPageHeight = initialConfig.pageSize.h;
|
|
259
208
|
let activeSectionMarginBottom = initialConfig.margins.bottom;
|
|
260
|
-
let
|
|
209
|
+
let renderedBreakState = INITIAL_RENDERED_BREAK_STATE;
|
|
261
210
|
for (let i = 0; i < blocks.length; i++) {
|
|
262
211
|
const block = blocks[i];
|
|
263
212
|
const measure = measures[i];
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
213
|
+
const renderedBreakNeedsSnap = measure.kind === "paragraph" && !paginator.fits(measure.totalHeight);
|
|
214
|
+
const hasExplicitPageBreak = hasPageBreakBefore(block);
|
|
215
|
+
const breakDecision = reconcileBreakBeforeBlock({
|
|
216
|
+
state: renderedBreakState,
|
|
217
|
+
block,
|
|
218
|
+
previousBlock: blocks[i - 1],
|
|
219
|
+
page: paginator.getCurrentState().page,
|
|
220
|
+
blocksById,
|
|
221
|
+
hasExplicitPageBreak,
|
|
222
|
+
renderedBreakNeedsSnap
|
|
223
|
+
});
|
|
224
|
+
if (breakDecision.forcePageBreak) paginator.forcePageBreak();
|
|
225
|
+
renderedBreakState = breakDecision.state;
|
|
271
226
|
const chain = keepNextChains.get(i);
|
|
272
227
|
if (chain && !midChainIndices.has(i)) {
|
|
273
228
|
const chainHeight = calculateChainHeight(chain, blocks, measures);
|
|
274
229
|
const pageBeforeChainLayout = paginator.getCurrentState().page.number;
|
|
275
230
|
paginator.ensureFits(chainHeight);
|
|
276
|
-
if (paginator.getCurrentState().page.number > pageBeforeChainLayout)
|
|
231
|
+
if (paginator.getCurrentState().page.number > pageBeforeChainLayout) renderedBreakState = recordReflowBoundary(renderedBreakState, true);
|
|
277
232
|
}
|
|
278
233
|
const pageBeforeBlockLayout = paginator.getCurrentState().page.number;
|
|
279
234
|
switch (block.kind) {
|
|
280
235
|
case "paragraph":
|
|
281
|
-
layoutParagraph(
|
|
236
|
+
layoutParagraph({
|
|
237
|
+
block,
|
|
238
|
+
measure,
|
|
239
|
+
paginator,
|
|
240
|
+
contentWidth: paginator.columnWidth,
|
|
241
|
+
footnoteHeightById: options.footnoteHeightById,
|
|
242
|
+
suppressSpaceBefore: breakDecision.suppressSpaceBefore
|
|
243
|
+
});
|
|
282
244
|
break;
|
|
283
245
|
case "table":
|
|
284
246
|
if (block.floating) layoutFloatingTable(block, measure, paginator, paginator.getContentWidth());
|
|
@@ -303,7 +265,9 @@ function layoutDocument(blocks, measures, options) {
|
|
|
303
265
|
break;
|
|
304
266
|
case "sectionBreak": {
|
|
305
267
|
const nextSectionConfig = sectionConfigs[sectionIdx + 1] ?? initialConfig;
|
|
306
|
-
|
|
268
|
+
let nextType = options.bodyBreakType ?? sectionBreakTypes[sectionIdx] ?? DEFAULT_SECTION_BREAK_TYPE;
|
|
269
|
+
if (sectionIdx + 1 < sectionBreakTypes.length) nextType = sectionBreakTypes[sectionIdx + 1] ?? DEFAULT_SECTION_BREAK_TYPE;
|
|
270
|
+
handleSectionBreak(block, paginator, nextSectionConfig, nextType, sectionIdx + 1);
|
|
307
271
|
const nextColumns = nextSectionConfig.columns;
|
|
308
272
|
const nextBreakIndex = breakIndices[sectionIdx + 1] ?? blocks.length;
|
|
309
273
|
const nextBreak = blocks[nextBreakIndex];
|
|
@@ -329,9 +293,13 @@ function layoutDocument(blocks, measures, options) {
|
|
|
329
293
|
}
|
|
330
294
|
default: break;
|
|
331
295
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
296
|
+
renderedBreakState = reconcileAfterBlock({
|
|
297
|
+
state: renderedBreakState,
|
|
298
|
+
block,
|
|
299
|
+
pageNumberBefore: pageBeforeBlockLayout,
|
|
300
|
+
pageNumberAfter: paginator.getCurrentState().page.number,
|
|
301
|
+
previousPage: paginator.pages[pageBeforeBlockLayout - 1]
|
|
302
|
+
});
|
|
335
303
|
}
|
|
336
304
|
if (paginator.pages.length === 0) paginator.getCurrentState();
|
|
337
305
|
return {
|
|
@@ -374,21 +342,11 @@ function getLineFootnoteRefs(block, fromRun, toRun, fnHeights) {
|
|
|
374
342
|
height
|
|
375
343
|
};
|
|
376
344
|
}
|
|
377
|
-
|
|
378
|
-
* Layout a paragraph block onto pages.
|
|
379
|
-
*
|
|
380
|
-
* When `footnoteHeightById` is provided, each line carrying a footnote
|
|
381
|
-
* ref additionally reserves space on its host page for the fn's
|
|
382
|
-
* content. Pagination decisions look at the line's effective height
|
|
383
|
-
* (`lineHeight + lineFnHeight`) so a line cannot land on a page that
|
|
384
|
-
* lacks room for both — preventing footnote overflow without the
|
|
385
|
-
* static-reservation iteration loop.
|
|
386
|
-
*/
|
|
387
|
-
function layoutParagraph(block, measure, paginator, contentWidth, footnoteHeightById) {
|
|
345
|
+
function layoutParagraph({ block, measure, paginator, contentWidth, footnoteHeightById, suppressSpaceBefore }) {
|
|
388
346
|
const lines = measure.lines;
|
|
389
347
|
if (lines.length === 0) {
|
|
390
|
-
const spaceBefore =
|
|
391
|
-
const spaceAfter =
|
|
348
|
+
const spaceBefore = suppressSpaceBefore ? 0 : getParagraphSpacingBefore(block);
|
|
349
|
+
const spaceAfter = getParagraphSpacingAfter(block);
|
|
392
350
|
const state = paginator.getCurrentState();
|
|
393
351
|
const fragment = {
|
|
394
352
|
kind: "paragraph",
|
|
@@ -406,8 +364,8 @@ function layoutParagraph(block, measure, paginator, contentWidth, footnoteHeight
|
|
|
406
364
|
paginator.addFragment(fragment, 0, spaceBefore, spaceAfter);
|
|
407
365
|
return;
|
|
408
366
|
}
|
|
409
|
-
const spaceBefore =
|
|
410
|
-
const spaceAfter =
|
|
367
|
+
const spaceBefore = suppressSpaceBefore ? 0 : getParagraphSpacingBefore(block);
|
|
368
|
+
const spaceAfter = getParagraphSpacingAfter(block);
|
|
411
369
|
let currentLineIndex = 0;
|
|
412
370
|
while (currentLineIndex < lines.length) {
|
|
413
371
|
const state = paginator.getCurrentState();
|
|
@@ -522,6 +480,7 @@ function layoutTable(block, measure, paginator, footnoteHeightById) {
|
|
|
522
480
|
const headerRowsHeight = getHeaderRowsHeight(measure, headerRowCount);
|
|
523
481
|
let currentRowIndex = 0;
|
|
524
482
|
const breakInfo = buildTableRowBreakInfo(block, measure);
|
|
483
|
+
const hasVerticalMerges = block.rows.some((row) => row.cells.some((cell) => (cell.rowSpan ?? 1) > 1));
|
|
525
484
|
const computeTableX = (columnIndex) => {
|
|
526
485
|
let x = paginator.getColumnX(columnIndex);
|
|
527
486
|
if (block.justification === "center") x += (paginator.columnWidth - measure.totalWidth) / 2;
|
|
@@ -534,7 +493,6 @@ function layoutTable(block, measure, paginator, footnoteHeightById) {
|
|
|
534
493
|
return x;
|
|
535
494
|
};
|
|
536
495
|
const getCurrentRowCapacity = (state = paginator.getCurrentState()) => state.rawContentBottom - state.topMargin;
|
|
537
|
-
const getCurrentAvailableHeight = (state = paginator.getCurrentState()) => state.contentBottom - state.cursorY;
|
|
538
496
|
const hasAdjacentPriorTableRows = (rowIndex, state = paginator.getCurrentState()) => {
|
|
539
497
|
const previous = state.page.fragments.at(-1);
|
|
540
498
|
return previous?.kind === "table" && previous.blockId === block.id && previous.toRow === rowIndex && previous.y + previous.height === state.cursorY && previous.x === computeTableX(state.columnIndex);
|
|
@@ -542,18 +500,21 @@ function layoutTable(block, measure, paginator, footnoteHeightById) {
|
|
|
542
500
|
const shouldRepeatHeaderRows = (rowIndex, consumed, state = paginator.getCurrentState()) => headerRowCount > 0 && rowIndex >= headerRowCount && !(consumed === 0 && hasAdjacentPriorTableRows(rowIndex, state));
|
|
543
501
|
const canSplitRow = (rowIndex, state = paginator.getCurrentState()) => {
|
|
544
502
|
const row = rows[rowIndex];
|
|
545
|
-
|
|
546
|
-
|
|
503
|
+
const sourceRow = block.rows[rowIndex];
|
|
504
|
+
if (!row || !sourceRow || sourceRow.cantSplit || sourceRow.isHeader || hasVerticalMerges) return false;
|
|
547
505
|
if ((breakInfo.breakOffsets[rowIndex]?.length ?? 0) <= 1) return false;
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
506
|
+
const freshHeaderOverhead = headerRowCount > 0 && rowIndex >= headerRowCount ? headerRowsHeight : 0;
|
|
507
|
+
const oversized = row.height + freshHeaderOverhead > getCurrentRowCapacity(state);
|
|
508
|
+
if (!oversized && (state.footnoteHeight > 0 || (rowFootnoteIds[rowIndex]?.length ?? 0) > 0)) return false;
|
|
509
|
+
const currentHeaderOverhead = shouldRepeatHeaderRows(rowIndex, 0, state) ? headerRowsHeight : 0;
|
|
510
|
+
const currentAvailableHeight = paginator.getAvailableHeight() - currentHeaderOverhead - state.trailingSpacing;
|
|
511
|
+
return oversized || row.height > currentAvailableHeight;
|
|
551
512
|
};
|
|
552
513
|
while (currentRowIndex < rows.length) {
|
|
553
|
-
const
|
|
514
|
+
const splittableRow = rows[currentRowIndex];
|
|
554
515
|
if (canSplitRow(currentRowIndex)) {
|
|
555
516
|
let consumed = 0;
|
|
556
|
-
while (consumed <
|
|
517
|
+
while (consumed < splittableRow.height) {
|
|
557
518
|
const sliceState = paginator.getCurrentState();
|
|
558
519
|
const repeatHeaderRows = shouldRepeatHeaderRows(currentRowIndex, consumed, sliceState);
|
|
559
520
|
const headerOverhead = repeatHeaderRows ? headerRowsHeight : 0;
|
|
@@ -565,11 +526,12 @@ function layoutTable(block, measure, paginator, footnoteHeightById) {
|
|
|
565
526
|
continue;
|
|
566
527
|
}
|
|
567
528
|
const from = consumed;
|
|
568
|
-
slice = (breakInfo.breakOffsets[currentRowIndex]?.find((o) => o > from) ??
|
|
529
|
+
slice = (breakInfo.breakOffsets[currentRowIndex]?.find((o) => o > from) ?? splittableRow.height) - consumed;
|
|
569
530
|
}
|
|
570
531
|
const sliceBottom = consumed + slice;
|
|
571
|
-
const
|
|
572
|
-
const
|
|
532
|
+
const continuationSkip = sliceBottom < splittableRow.height ? getRowContinuationSkip(breakInfo, currentRowIndex, sliceBottom) : 0;
|
|
533
|
+
const nextConsumed = Math.min(splittableRow.height, sliceBottom + continuationSkip);
|
|
534
|
+
const moreAfter = !(nextConsumed >= splittableRow.height) || currentRowIndex + 1 < rows.length;
|
|
573
535
|
const fragmentHeight = headerOverhead + slice;
|
|
574
536
|
const sliceFragment = {
|
|
575
537
|
kind: "table",
|
|
@@ -586,14 +548,14 @@ function layoutTable(block, measure, paginator, footnoteHeightById) {
|
|
|
586
548
|
...moreAfter ? { continuesOnNext: true } : {},
|
|
587
549
|
...repeatHeaderRows ? { headerRowCount } : {},
|
|
588
550
|
...consumed > 0 ? { topClip: consumed } : {},
|
|
589
|
-
...
|
|
551
|
+
...sliceBottom >= splittableRow.height ? {} : { bottomClip: sliceBottom },
|
|
590
552
|
...block.sdtGroups ? { sdtGroups: block.sdtGroups } : {}
|
|
591
553
|
};
|
|
592
554
|
const sliceResult = paginator.addFragment(sliceFragment, fragmentHeight, 0, 0);
|
|
593
555
|
sliceFragment.y = sliceResult.y;
|
|
594
556
|
sliceFragment.x = computeTableX(sliceResult.state.columnIndex);
|
|
595
|
-
consumed =
|
|
596
|
-
if (consumed <
|
|
557
|
+
consumed = nextConsumed;
|
|
558
|
+
if (consumed < splittableRow.height) paginator.forceColumnBreak();
|
|
597
559
|
}
|
|
598
560
|
currentRowIndex += 1;
|
|
599
561
|
continue;
|
|
@@ -929,4 +891,4 @@ function handleSectionBreak(_block, paginator, nextSectionConfig, nextSectionTyp
|
|
|
929
891
|
paginator.updateColumns(nextSectionConfig.columns ?? DEFAULT_COLUMNS);
|
|
930
892
|
}
|
|
931
893
|
//#endregion
|
|
932
|
-
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, scheduleSectionBreak, tableColumnsArePinned };
|
|
894
|
+
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, scheduleSectionBreak, tableColumnsArePinned };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLineBreakProviderGeneration } from "./lineBreakProvider.js";
|
|
1
2
|
//#region src/layout-engine/measure/cache.ts
|
|
2
3
|
/**
|
|
3
4
|
* Current max size for text width cache
|
|
@@ -152,10 +153,10 @@ const paragraphMeasureCache = /* @__PURE__ */ new Map();
|
|
|
152
153
|
* Used as cache key to identify identical content
|
|
153
154
|
*/
|
|
154
155
|
function hashParagraphBlock(block) {
|
|
155
|
-
const parts = [];
|
|
156
|
-
for (const run of block.runs) if (run.kind === "text") parts.push(`t:${run.text}|${run.fontFamily}|${run.eastAsiaFontFamily}|${run.fontSize}|${run.bold}|${run.italic}|${run.allCaps}|${run.smallCaps}|${run.horizontalScale}|${run.letterSpacing}`);
|
|
156
|
+
const parts = [`lbp:${getLineBreakProviderGeneration()}`];
|
|
157
|
+
for (const run of block.runs) if (run.kind === "text") parts.push(`t:${run.text}|${run.fontFamily}|${run.eastAsiaFontFamily}|${run.fontSize}|${run.bold}|${run.italic}|${run.allCaps}|${run.smallCaps}|${run.horizontalScale}|${run.letterSpacing}|${run.language?.val}|${run.language?.eastAsia}|${run.language?.bidi}`);
|
|
157
158
|
else if (run.kind === "tab") parts.push(`tab:${run.width}`);
|
|
158
|
-
else if (run.kind === "image") parts.push(`img:${run.width}x${run.height}`);
|
|
159
|
+
else if (run.kind === "image") parts.push(`img:${run.width}x${run.height}:${run.exactLineHeight === true ? "exact" : "text"}`);
|
|
159
160
|
else if (run.kind === "lineBreak") parts.push("br");
|
|
160
161
|
const attrs = block.attrs;
|
|
161
162
|
if (attrs) {
|
|
@@ -167,6 +168,13 @@ function hashParagraphBlock(block) {
|
|
|
167
168
|
if (attrs.defaultFontFamily != null) parts.push(`dff:${attrs.defaultFontFamily}`);
|
|
168
169
|
if (attrs.suppressEmptyParagraphHeight) parts.push("sup");
|
|
169
170
|
if (attrs.reserveEmptyOutlineHeight) parts.push("outline-empty-reserve");
|
|
171
|
+
if (attrs.kinsoku !== void 0) parts.push(`kinsoku:${attrs.kinsoku}`);
|
|
172
|
+
if (attrs.overflowPunctuation !== void 0) parts.push(`overflow-punct:${attrs.overflowPunctuation}`);
|
|
173
|
+
if (attrs.suppressAutoHyphens !== void 0) parts.push(`suppress-auto-hyphens:${attrs.suppressAutoHyphens}`);
|
|
174
|
+
const automaticHyphenation = attrs.automaticHyphenation;
|
|
175
|
+
if (automaticHyphenation) parts.push(`auto-hyphens:${automaticHyphenation.doNotHyphenateCaps}|${automaticHyphenation.consecutiveLineLimit}`);
|
|
176
|
+
const lineBreakRules = attrs.lineBreakRules;
|
|
177
|
+
if (lineBreakRules) parts.push(`line-break-rules:${lineBreakRules.noLineBreaksBefore?.language}|${lineBreakRules.noLineBreaksBefore?.characters}|${lineBreakRules.noLineBreaksAfter?.language}|${lineBreakRules.noLineBreaksAfter?.characters}|${lineBreakRules.useLegacyEthiopicAmharicRules}`);
|
|
170
178
|
const borders = attrs.borders;
|
|
171
179
|
if (borders) {
|
|
172
180
|
const signature = (border) => border ? `${border.width ?? ""},${border.style ?? ""},${border.color ?? ""}` : "";
|
|
@@ -44,6 +44,7 @@ function isFontFingerprintMatch(context, expectedWidth) {
|
|
|
44
44
|
function measureEntry(entry) {
|
|
45
45
|
const context = getCtx();
|
|
46
46
|
context.font = entry.font;
|
|
47
|
+
context.fontKerning = entry.fontKerning;
|
|
47
48
|
if (!isFontFingerprintMatch(context, entry.fontFingerprintWidth)) return null;
|
|
48
49
|
let width = context.measureText(entry.text).width;
|
|
49
50
|
const codePoints = countCodePoints(entry.text);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { FontMetrics, FontStyle, RunMeasurement, TextMeasurement } from "./measureTypes.js";
|
|
2
2
|
import { MeasureProvider, getFontMetrics, getMeasureProvider, measureRun, measureText, measureTextWidth, resetMeasureProvider, setMeasureProvider } from "./measureProvider.js";
|
|
3
3
|
import { buildFontString, findCharacterAtX, getXForCharacter, halfPtToPx, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx } from "./measureHelpers.js";
|
|
4
|
+
import { LineBreakPolicy, LineBreakProvider, defaultLineBreakProvider, getLineBreakProvider, getLineBreakProviderGeneration, resetLineBreakProvider, setLineBreakProvider } from "./lineBreakProvider.js";
|
|
4
5
|
import { FloatingExclusionRect, FloatingImageZone, FloatingLineMargins, FloatingLineSegmentZone, WrapTextDirection, getFloatingAvailableWidth, getFloatingMargins, rectsToFloatingZones } from "./floatingZones.js";
|
|
5
6
|
import { clampFloatingWrapMargins } from "./clampFloatingWrapMargins.js";
|
|
6
7
|
import { MeasureParagraphOptions, getRunCharWidths, measureParagraph, measureParagraphs } from "./measureParagraph.js";
|
|
7
8
|
import { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTotalCacheSize, hashParagraphBlock, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize } from "./cache.js";
|
|
8
9
|
import { FolioMeasurementFeatureFlags, isWorkerFontMetricsEnabled, setFolioMeasurementFlags } from "./featureFlags.js";
|
|
9
|
-
export { type FloatingExclusionRect, type FloatingImageZone, type FloatingLineMargins, type FloatingLineSegmentZone, type FolioMeasurementFeatureFlags, type FontMetrics, type FontStyle, type MeasureParagraphOptions, type MeasureProvider, type RunMeasurement, type TextMeasurement, type WrapTextDirection, buildFontString, clampFloatingWrapMargins, clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, findCharacterAtX, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFloatingAvailableWidth, getFloatingMargins, getFontCacheSize, getFontMetrics, getMeasureProvider, getParagraphCacheSize, getRunCharWidths, getTextCacheSize, getTotalCacheSize, getXForCharacter, halfPtToPx, hashParagraphBlock, isWorkerFontMetricsEnabled, measureParagraph, measureParagraphs, measureRun, measureText, measureTextWidth, ptToPx, pxToHalfPt, pxToPt, pxToTwips, rectsToFloatingZones, resetMeasureProvider, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFolioMeasurementFlags, setFontCacheSize, setMeasureProvider, setParagraphCacheSize, setTextCacheSize, twipsToPx };
|
|
10
|
+
export { type FloatingExclusionRect, type FloatingImageZone, type FloatingLineMargins, type FloatingLineSegmentZone, type FolioMeasurementFeatureFlags, type FontMetrics, type FontStyle, type LineBreakPolicy, type LineBreakProvider, type MeasureParagraphOptions, type MeasureProvider, type RunMeasurement, type TextMeasurement, type WrapTextDirection, buildFontString, clampFloatingWrapMargins, clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, defaultLineBreakProvider, findCharacterAtX, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFloatingAvailableWidth, getFloatingMargins, getFontCacheSize, getFontMetrics, getLineBreakProvider, getLineBreakProviderGeneration, getMeasureProvider, getParagraphCacheSize, getRunCharWidths, getTextCacheSize, getTotalCacheSize, getXForCharacter, halfPtToPx, hashParagraphBlock, isWorkerFontMetricsEnabled, measureParagraph, measureParagraphs, measureRun, measureText, measureTextWidth, ptToPx, pxToHalfPt, pxToPt, pxToTwips, rectsToFloatingZones, resetLineBreakProvider, resetMeasureProvider, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFolioMeasurementFlags, setFontCacheSize, setLineBreakProvider, setMeasureProvider, setParagraphCacheSize, setTextCacheSize, twipsToPx };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getFontMetrics, getMeasureProvider, measureRun, measureText, measureTextWidth, resetMeasureProvider, setMeasureProvider } from "./measureProvider.js";
|
|
2
2
|
import { buildFontString, findCharacterAtX, getXForCharacter, halfPtToPx, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx } from "./measureHelpers.js";
|
|
3
|
+
import { defaultLineBreakProvider, getLineBreakProvider, getLineBreakProviderGeneration, resetLineBreakProvider, setLineBreakProvider } from "./lineBreakProvider.js";
|
|
3
4
|
import { clampFloatingWrapMargins } from "./clampFloatingWrapMargins.js";
|
|
4
5
|
import { getFloatingAvailableWidth, getFloatingMargins, rectsToFloatingZones } from "./floatingZones.js";
|
|
5
6
|
import { getRunCharWidths, measureParagraph, measureParagraphs } from "./measureParagraph.js";
|
|
6
7
|
import { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTotalCacheSize, hashParagraphBlock, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize } from "./cache.js";
|
|
7
8
|
import { isWorkerFontMetricsEnabled, setFolioMeasurementFlags } from "./featureFlags.js";
|
|
8
|
-
export { buildFontString, clampFloatingWrapMargins, clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, findCharacterAtX, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFloatingAvailableWidth, getFloatingMargins, getFontCacheSize, getFontMetrics, getMeasureProvider, getParagraphCacheSize, getRunCharWidths, getTextCacheSize, getTotalCacheSize, getXForCharacter, halfPtToPx, hashParagraphBlock, isWorkerFontMetricsEnabled, measureParagraph, measureParagraphs, measureRun, measureText, measureTextWidth, ptToPx, pxToHalfPt, pxToPt, pxToTwips, rectsToFloatingZones, resetMeasureProvider, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFolioMeasurementFlags, setFontCacheSize, setMeasureProvider, setParagraphCacheSize, setTextCacheSize, twipsToPx };
|
|
9
|
+
export { buildFontString, clampFloatingWrapMargins, clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, defaultLineBreakProvider, findCharacterAtX, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFloatingAvailableWidth, getFloatingMargins, getFontCacheSize, getFontMetrics, getLineBreakProvider, getLineBreakProviderGeneration, getMeasureProvider, getParagraphCacheSize, getRunCharWidths, getTextCacheSize, getTotalCacheSize, getXForCharacter, halfPtToPx, hashParagraphBlock, isWorkerFontMetricsEnabled, measureParagraph, measureParagraphs, measureRun, measureText, measureTextWidth, ptToPx, pxToHalfPt, pxToPt, pxToTwips, rectsToFloatingZones, resetLineBreakProvider, resetMeasureProvider, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFolioMeasurementFlags, setFontCacheSize, setLineBreakProvider, setMeasureProvider, setParagraphCacheSize, setTextCacheSize, twipsToPx };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/layout-engine/measure/lineBreakProvider.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Replaceable line-break policy for the layout engine.
|
|
4
|
+
*
|
|
5
|
+
* Providers return UTF-16 offsets so their output composes directly with the
|
|
6
|
+
* run and ProseMirror positions used by the rest of the layout pipeline. The
|
|
7
|
+
* default provider uses the platform's Unicode segmenter, then applies the
|
|
8
|
+
* OOXML line-edge restrictions that are available in the flow model.
|
|
9
|
+
*/
|
|
10
|
+
type LineBreakPolicy = {
|
|
11
|
+
/** BCP-47 language tag resolved from `w:lang` for this run. */locale?: string; /** Apply East Asian first/last-character restrictions (`w:kinsoku`). */
|
|
12
|
+
kinsoku?: boolean; /** Document replacement list: characters that may not begin a line. */
|
|
13
|
+
noLineBreaksBefore?: string; /** Document replacement list: characters that may not end a line. */
|
|
14
|
+
noLineBreaksAfter?: string; /** Use the legacy Ethiopic/Amharic compatibility behavior. */
|
|
15
|
+
useLegacyEthiopicAmharicRules?: boolean; /** Keep words made entirely of capital letters unhyphenated. */
|
|
16
|
+
doNotHyphenateCaps?: boolean; /** The run renders with the DOCX all-caps transform. */
|
|
17
|
+
renderedAllCaps?: boolean;
|
|
18
|
+
};
|
|
19
|
+
type LineBreakProvider = {
|
|
20
|
+
/** Legal soft-wrap offsets, in ascending UTF-16 order. */findBreaks: (text: string, policy?: LineBreakPolicy) => number[]; /** Grapheme-safe emergency-wrap offsets, in ascending UTF-16 order. */
|
|
21
|
+
findGraphemeBreaks: (text: string, policy?: LineBreakPolicy) => number[]; /** Dictionary-based discretionary hyphen offsets, in ascending UTF-16 order. */
|
|
22
|
+
findHyphenationBreaks?: (text: string, policy?: LineBreakPolicy) => number[]; /** Whether a trailing grapheme may overhang the line edge. */
|
|
23
|
+
isHangingPunctuation?: (text: string, policy?: LineBreakPolicy) => boolean;
|
|
24
|
+
};
|
|
25
|
+
declare const MAX_HYPHENATION_WORD_LENGTH = 256;
|
|
26
|
+
declare const defaultLineBreakProvider: LineBreakProvider;
|
|
27
|
+
declare const getLineBreakProvider: () => LineBreakProvider;
|
|
28
|
+
/** Changes whenever the active provider changes, so layout caches cannot go stale. */
|
|
29
|
+
declare const getLineBreakProviderGeneration: () => number;
|
|
30
|
+
declare const setLineBreakProvider: (provider: LineBreakProvider) => void;
|
|
31
|
+
declare const resetLineBreakProvider: () => void;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { LineBreakPolicy, LineBreakProvider, MAX_HYPHENATION_WORD_LENGTH, defaultLineBreakProvider, getLineBreakProvider, getLineBreakProviderGeneration, resetLineBreakProvider, setLineBreakProvider };
|