@stll/folio-core 0.47.7 → 0.48.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/controller/fontReadiness.js +3 -3
- package/dist/controller/hyphenationReadiness.d.ts +19 -0
- package/dist/controller/hyphenationReadiness.js +47 -0
- package/dist/controller/layoutPipeline.d.ts +3 -0
- package/dist/controller/layoutPipeline.js +59 -17
- package/dist/display-list/build/buildDisplayList.js +39 -12
- package/dist/display-list/build/pageFurniture.d.ts +7 -1
- package/dist/display-list/build/pageFurniture.js +21 -8
- package/dist/display-list/build/paragraphPrimitives.js +5 -4
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +77 -62
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +57 -45
- package/dist/docx/containerChildren.d.ts +21 -8
- package/dist/docx/containerChildren.js +39 -9
- package/dist/docx/documentParser.d.ts +5 -1
- package/dist/docx/documentParser.js +8 -5
- package/dist/docx/documentSectionFacts.d.ts +22 -0
- package/dist/docx/documentSectionFacts.js +43 -0
- package/dist/docx/fieldParser.d.ts +8 -1
- package/dist/docx/fieldParser.js +47 -3
- package/dist/docx/fontTableParser.js +34 -27
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +15 -12
- package/dist/docx/groupDrawingParser.d.ts +2 -1
- package/dist/docx/groupDrawingParser.js +3 -6
- package/dist/docx/headerFooterParser.d.ts +7 -2
- package/dist/docx/headerFooterParser.js +15 -5
- package/dist/docx/hyperlinkParser.d.ts +48 -36
- package/dist/docx/hyperlinkParser.js +97 -82
- package/dist/docx/numberingParser.js +108 -84
- package/dist/docx/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +381 -362
- package/dist/docx/paragraphProperties.js +123 -109
- package/dist/docx/paragraphPropertySource.d.ts +6 -1
- package/dist/docx/paragraphPropertySource.js +9 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +17 -6
- package/dist/docx/parser.d.ts +7 -1
- package/dist/docx/parser.js +33 -16
- package/dist/docx/previewBudget.d.ts +55 -33
- package/dist/docx/previewBudget.js +59 -65
- package/dist/docx/rezip.js +41 -58
- package/dist/docx/runParser.d.ts +4 -1
- package/dist/docx/runParser.js +172 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/serializer/paragraphSerializer.js +42 -38
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -0
- package/dist/docx/streamingXmlParser.d.ts +6 -2
- package/dist/docx/streamingXmlParser.js +12 -7
- package/dist/docx/styleParser.js +34 -8
- package/dist/docx/tableParser.d.ts +21 -12
- package/dist/docx/tableParser.js +518 -441
- package/dist/docx/textBoxParser.d.ts +8 -3
- package/dist/docx/textBoxParser.js +3 -3
- package/dist/docx/verbatimCapture.d.ts +10 -8
- package/dist/docx/verbatimCapture.js +45 -2
- package/dist/docx/vmlImageParser.d.ts +15 -13
- package/dist/docx/vmlImageParser.js +75 -60
- package/dist/docx/vmlPreview.d.ts +3 -3
- package/dist/docx/vmlPreview.js +3 -4
- package/dist/docx/xmlNamespaceContext.d.ts +9 -0
- package/dist/docx/xmlNamespaceContext.js +54 -0
- package/dist/docx/xmlParser.d.ts +6 -3
- package/dist/docx/xmlParser.js +11 -41
- package/dist/docx/xmlResourceLimits.d.ts +2 -1
- package/dist/docx/xmlResourceLimits.js +4 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/headless-layout.d.ts +11 -2
- package/dist/headless-layout.js +153 -107
- package/dist/internal/paragraphFormattingSerialization.js +3 -3
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
- package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
- package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
- package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
- package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +258 -35
- package/dist/layout-bridge/engine/hitTest.js +5 -3
- package/dist/layout-bridge/engine/selectionRects.js +5 -3
- package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
- package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +70 -11
- package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
- package/dist/layout-engine/justificationCompatibility.js +9 -5
- package/dist/layout-engine/keep-together.d.ts +11 -5
- package/dist/layout-engine/keep-together.js +39 -16
- package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
- package/dist/layout-engine/layoutInstrumentation.js +8 -1
- package/dist/layout-engine/measure/advanceComposition.js +4 -7
- package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
- package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
- package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
- package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
- package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
- package/dist/layout-engine/measure/lineBreaks.js +10 -3
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
- package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
- package/dist/layout-engine/measure/measureBlocks.js +42 -8
- package/dist/layout-engine/measure/measureContainer.js +5 -5
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +21 -5
- package/dist/layout-engine/measure/measureParagraph.js +109 -30
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
- package/dist/layout-engine/measure/tabCalculator.js +2 -1
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +51 -19
- package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
- package/dist/layout-engine/measure/tableCellGrid.js +45 -5
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
- package/dist/layout-engine/noteAreaFlow.js +83 -0
- package/dist/layout-engine/paginator.d.ts +10 -1
- package/dist/layout-engine/paginator.js +13 -1
- package/dist/layout-engine/tableRowBreak.js +3 -1
- package/dist/layout-engine/types.d.ts +89 -3
- package/dist/layout-engine/types.js +96 -1
- package/dist/layout-painter/index.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +32 -83
- package/dist/layout-painter/renderParagraph.d.ts +6 -1
- package/dist/layout-painter/renderParagraph.js +34 -22
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +43 -11
- package/dist/prosemirror/conversion/fromProseDoc.js +8 -1
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +77 -41
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +2 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +2 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +13 -1
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- package/dist/utils/createDocument.js +10 -1
- package/dist/utils/scriptSegments.d.ts +33 -4
- package/dist/utils/scriptSegments.js +39 -6
- package/dist/utils/textFormattingMerge.d.ts +17 -3
- package/dist/utils/textFormattingMerge.js +18 -12
- package/dist/utils/trailingText.d.ts +22 -0
- package/dist/utils/trailingText.js +32 -0
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildFontAlternates, getFontAlternate } from "../fonts/fontAlternates.js";
|
|
2
|
+
import { DEFAULT_FONT_FAMILY } from "../layout-engine/measure/measureHelpers.js";
|
|
2
3
|
import { expectFontFamilyMarkAttrs, expectParagraphAttrs } from "../prosemirror/attrs/index.js";
|
|
3
4
|
import { parseFontFamilyList, resolveFontFamily } from "../utils/fontResolver.js";
|
|
4
5
|
//#region src/controller/fontReadiness.ts
|
|
@@ -11,7 +12,6 @@ function documentFontsAreLoaded() {
|
|
|
11
12
|
return !fontSet || fontSet.status === "loaded";
|
|
12
13
|
}
|
|
13
14
|
const INITIAL_LAYOUT_FONT_TIMEOUT_MS = 2e3;
|
|
14
|
-
const DEFAULT_LAYOUT_FONT_FAMILY = "Calibri";
|
|
15
15
|
const CSS_GENERIC_FONT_FAMILIES = /* @__PURE__ */ new Set([
|
|
16
16
|
"serif",
|
|
17
17
|
"sans-serif",
|
|
@@ -54,7 +54,7 @@ function collectInitialLayoutFontFamilies(documentModel, pmDoc) {
|
|
|
54
54
|
function collectInitialLayoutFontFaces(documentModel, pmDoc) {
|
|
55
55
|
const faces = /* @__PURE__ */ new Map();
|
|
56
56
|
const fontAlternates = buildFontAlternates(documentModel?.package.fontTable);
|
|
57
|
-
addLayoutFontFamilyFace(faces,
|
|
57
|
+
addLayoutFontFamilyFace(faces, DEFAULT_FONT_FAMILY, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
|
|
58
58
|
for (const family of documentModel?.requiredFonts ?? []) addLayoutFontFamilyFace(faces, family, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
|
|
59
59
|
addLayoutFontFamilyFace(faces, documentModel?.package.theme?.fontScheme?.majorFont?.latin, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
|
|
60
60
|
addLayoutFontFamilyFace(faces, documentModel?.package.theme?.fontScheme?.minorFont?.latin, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
|
|
@@ -75,7 +75,7 @@ function collectProseMirrorFontFaces(faces, node, inheritedTextFormatting, fontA
|
|
|
75
75
|
if (node.type.name === "paragraph") addTextFormattingFontFaces(faces, expectParagraphAttrs(node).listMarkerFormatting, fontAlternates);
|
|
76
76
|
if (node.isText) {
|
|
77
77
|
const descriptor = layoutDescriptorFromFormattingAndMarks(textFormatting, node.marks);
|
|
78
|
-
addLayoutFontFamilyFace(faces, readFontFamilyMarkAttrs(node.marks) ?? textFormatting?.fontFamily ??
|
|
78
|
+
addLayoutFontFamilyFace(faces, readFontFamilyMarkAttrs(node.marks) ?? textFormatting?.fontFamily ?? "Times New Roman", descriptor, fontAlternates);
|
|
79
79
|
}
|
|
80
80
|
node.forEach((child) => {
|
|
81
81
|
collectProseMirrorFontFaces(faces, child, textFormatting, fontAlternates);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HyphenationDictionaryError, HyphenationDictionaryId } from "../layout-engine/measure/hyphenationDictionaries.js";
|
|
2
|
+
//#region src/controller/hyphenationReadiness.d.ts
|
|
3
|
+
type HyphenationReadiness = {
|
|
4
|
+
/** Follow up on the dictionaries one layout run lacked. */
|
|
5
|
+
track: (missing: ReadonlySet<HyphenationDictionaryId>) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Ignore loads still pending, as on unmount. A later `track` follows up
|
|
8
|
+
* afresh, so an adapter whose lifecycle re-attaches (React Strict Mode
|
|
9
|
+
* effects) keeps working.
|
|
10
|
+
*/
|
|
11
|
+
cancel: () => void;
|
|
12
|
+
};
|
|
13
|
+
type HyphenationReadinessOptions = {
|
|
14
|
+
relayout: () => void;
|
|
15
|
+
onError: (error: HyphenationDictionaryError) => void;
|
|
16
|
+
};
|
|
17
|
+
declare const createHyphenationReadiness: ({ relayout, onError }: HyphenationReadinessOptions) => HyphenationReadiness;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HyphenationReadiness, HyphenationReadinessOptions, createHyphenationReadiness };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { requestHyphenationDictionary } from "../layout-engine/measure/hyphenationDictionaries.js";
|
|
2
|
+
//#region src/controller/hyphenationReadiness.ts
|
|
3
|
+
/**
|
|
4
|
+
* Per-editor follow-up for hyphenation dictionaries a layout run lacked.
|
|
5
|
+
*
|
|
6
|
+
* Framework-neutral so both adapters share one implementation. The layout
|
|
7
|
+
* pipeline hands {@link HyphenationReadiness.track} the dictionaries its run
|
|
8
|
+
* requested but could not use; this editor then re-runs layout when one loads
|
|
9
|
+
* (the load has already invalidated measured paragraphs) and reports a failed
|
|
10
|
+
* one once. Editors that never asked for a dictionary hear nothing about it,
|
|
11
|
+
* and an editor mounted after a failure still learns of it on its first run.
|
|
12
|
+
*/
|
|
13
|
+
const createHyphenationReadiness = ({ relayout, onError }) => {
|
|
14
|
+
let epoch = 0;
|
|
15
|
+
const pending = /* @__PURE__ */ new Set();
|
|
16
|
+
const reported = /* @__PURE__ */ new Set();
|
|
17
|
+
const follow = async (dictionary) => {
|
|
18
|
+
const startedIn = epoch;
|
|
19
|
+
pending.add(dictionary);
|
|
20
|
+
const settled = await requestHyphenationDictionary(dictionary);
|
|
21
|
+
if (startedIn !== epoch) return;
|
|
22
|
+
pending.delete(dictionary);
|
|
23
|
+
switch (settled.status) {
|
|
24
|
+
case "loaded":
|
|
25
|
+
relayout();
|
|
26
|
+
return;
|
|
27
|
+
case "failed":
|
|
28
|
+
if (!reported.has(dictionary)) {
|
|
29
|
+
reported.add(dictionary);
|
|
30
|
+
onError(settled.error);
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
default:
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
track: (missing) => {
|
|
38
|
+
for (const dictionary of missing) if (!pending.has(dictionary)) follow(dictionary);
|
|
39
|
+
},
|
|
40
|
+
cancel: () => {
|
|
41
|
+
epoch += 1;
|
|
42
|
+
pending.clear();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { createHyphenationReadiness };
|
|
@@ -3,6 +3,7 @@ import { TemplatePreviewEntry, TemplatePreviewHiddenRange } from "../prosemirror
|
|
|
3
3
|
import { ColumnLayout, FlowBlock, FootnoteContent, HeaderFooterContent, Layout, Measure, PageHeaderFooterRefs, PageMargins } from "../layout-engine/types.js";
|
|
4
4
|
import { LayoutRunReason } from "../layout-engine/layoutInstrumentation.js";
|
|
5
5
|
import { DirtyRange } from "../paged-layout/incrementalMeasure.js";
|
|
6
|
+
import { HyphenationReadiness } from "./hyphenationReadiness.js";
|
|
6
7
|
import { ConvertHeaderFooterOptions, HeaderFooterMetrics } from "../layout-bridge/convert/headerFooterLayout.js";
|
|
7
8
|
import "../layout-engine/index.js";
|
|
8
9
|
import { FootnoteRenderItem } from "../layout-painter/renderPage.js";
|
|
@@ -74,6 +75,8 @@ type LayoutPipelineDeps<THfPMs> = {
|
|
|
74
75
|
pageRenderer?: PageRendererName;
|
|
75
76
|
emptyTemplatePreviewEntries: readonly TemplatePreviewEntry[];
|
|
76
77
|
emptyTemplatePreviewHidden: readonly TemplatePreviewHiddenRange[];
|
|
78
|
+
/** Follows up on the hyphenation dictionaries a run lacked (relayout or error). */
|
|
79
|
+
hyphenationReadiness: HyphenationReadiness;
|
|
77
80
|
};
|
|
78
81
|
declare function runLayoutPipeline<THfPMs>(deps: LayoutPipelineDeps<THfPMs>, state: EditorState, options?: LayoutRunOptions): LayoutOutcome;
|
|
79
82
|
//#endregion
|
|
@@ -9,13 +9,16 @@ import { buildHeaderFooterFieldValues, fieldValuesEqual, resolveFieldValues } fr
|
|
|
9
9
|
import { buildSectionPageCounts } from "../fields/sectionPageCounts.js";
|
|
10
10
|
import { buildSeqValues } from "../fields/seqValues.js";
|
|
11
11
|
import { buildFontAlternates } from "../fonts/fontAlternates.js";
|
|
12
|
+
import { prepareEndnoteAreas, resolveEndnotePosition, spliceEndnoteAreas, trailingEndnoteIds } from "../layout-bridge/convert/endnoteLayout.js";
|
|
12
13
|
import { buildFootnoteContentMap, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, remapNoteMarkerText } from "../layout-bridge/convert/footnoteLayout.js";
|
|
13
14
|
import { applyTemplatePreviewToBlocks } from "../layout-bridge/convert/templatePreviewFlow.js";
|
|
14
15
|
import { toFlowBlocks } from "../layout-bridge/convert/toFlowBlocks.js";
|
|
15
16
|
import { getColumns } from "../layout-bridge/sectionColumns.js";
|
|
17
|
+
import { resolveAnchorLayoutInCellCompatibility } from "../layout-engine/anchorLayoutInCellCompatibility.js";
|
|
16
18
|
import { layoutDocument } from "../layout-engine/index.js";
|
|
17
19
|
import { resolveJustificationCompatibility } from "../layout-engine/justificationCompatibility.js";
|
|
18
20
|
import { recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart } from "../layout-engine/layoutInstrumentation.js";
|
|
21
|
+
import { collectRequestedHyphenationDictionaries } from "../layout-engine/measure/hyphenationDictionaries.js";
|
|
19
22
|
import { measureBlocks, measureSingleBlockWithoutFloatingZones } from "../layout-engine/measure/measureBlocks.js";
|
|
20
23
|
import { installCanvasMeasureProvider } from "../layout-engine/measure/measureContainer.js";
|
|
21
24
|
import { resolveEffectiveParagraphSpacingTree } from "../layout-engine/paragraphSpacing.js";
|
|
@@ -100,6 +103,11 @@ function attachAuthoredMarginsToLayoutPages(layout, options) {
|
|
|
100
103
|
} : layout;
|
|
101
104
|
}
|
|
102
105
|
function runLayoutPipeline(deps, state, options = {}) {
|
|
106
|
+
const { result, missing } = collectRequestedHyphenationDictionaries(() => runLayoutPipelineMeasured(deps, state, options));
|
|
107
|
+
deps.hyphenationReadiness.track(missing);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
function runLayoutPipelineMeasured(deps, state, options) {
|
|
103
111
|
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, pageRenderer = PAGE_RENDERER.legacy, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES, emptyTemplatePreviewHidden: EMPTY_TEMPLATE_PREVIEW_HIDDEN } = deps;
|
|
104
112
|
let outcome = {};
|
|
105
113
|
let pendingArtifacts;
|
|
@@ -131,6 +139,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
131
139
|
if (justificationCompatibility) flowOpts.justificationCompatibility = justificationCompatibility;
|
|
132
140
|
const tableIndentCompatibility = resolveTableIndentCompatibility(documentSettings?.compatibilityMode);
|
|
133
141
|
if (tableIndentCompatibility) flowOpts.tableIndentCompatibility = tableIndentCompatibility;
|
|
142
|
+
if (resolveAnchorLayoutInCellCompatibility(documentSettings?.compatibilityMode)) flowOpts.forceAnchorLayoutInCell = true;
|
|
134
143
|
if (documentSettings?.autoHyphenation === true) flowOpts.automaticHyphenation = {
|
|
135
144
|
enabled: true,
|
|
136
145
|
...documentSettings.doNotHyphenateCaps !== void 0 ? { doNotHyphenateCaps: documentSettings.doNotHyphenateCaps } : {},
|
|
@@ -139,6 +148,9 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
139
148
|
};
|
|
140
149
|
const finalSectionDocumentGridLinePitchTwips = resolveDocumentGridLinePitch(document?.package.document.sections?.at(-1)?.properties.docGrid);
|
|
141
150
|
if (finalSectionDocumentGridLinePitchTwips !== void 0) flowOpts.finalSectionDocumentGridLinePitchTwips = finalSectionDocumentGridLinePitchTwips;
|
|
151
|
+
const endnotePosition = resolveEndnotePosition(document?.package.settings?.endnotePr?.position, document?.package.document.sections?.at(-1)?.properties);
|
|
152
|
+
const bodyTrailingEndnoteIds = trailingEndnoteIds(document?.package.endnotes, endnotePosition);
|
|
153
|
+
if (bodyTrailingEndnoteIds.size > 0) flowOpts.trailingEndnoteIds = bodyTrailingEndnoteIds;
|
|
142
154
|
let newBlocks = toFlowBlocks(document === null ? state.doc.type.create({
|
|
143
155
|
...state.doc.attrs,
|
|
144
156
|
_finalSectionStart: sectionProperties?.sectionStart ?? null
|
|
@@ -166,7 +178,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
166
178
|
const footnoteDisplayNumbers = documentFootnotes ? computeNoteDisplayNumbers(documentFootnotes, footnoteRefs.map((ref) => ref.footnoteId)) : void 0;
|
|
167
179
|
const documentEndnotes = document?.package.endnotes;
|
|
168
180
|
const endnoteDisplayNumbers = documentEndnotes ? computeNoteDisplayNumbers(documentEndnotes, collectEndnoteRefs(newBlocks).map((ref) => ref.endnoteId)) : void 0;
|
|
169
|
-
const endnoteNumberFormat = document?.package.document.sections?.at(-1)?.properties.endnotePr?.numFmt ?? "lowerRoman";
|
|
181
|
+
const endnoteNumberFormat = document?.package.document.sections?.at(-1)?.properties.endnotePr?.numFmt ?? document?.package.settings?.endnotePr?.numFmt ?? "lowerRoman";
|
|
170
182
|
const endnoteTexts = endnoteDisplayNumbers ? formatEndnoteTexts(endnoteDisplayNumbers, (displayNumber) => formatOoxmlCounter(displayNumber, endnoteNumberFormat)) : void 0;
|
|
171
183
|
newBlocks = remapNoteMarkerText(newBlocks, {
|
|
172
184
|
...footnoteDisplayNumbers ? { footnoteNumbers: footnoteDisplayNumbers } : {},
|
|
@@ -302,6 +314,36 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
302
314
|
};
|
|
303
315
|
outcome.measures = newMeasures;
|
|
304
316
|
recordPhaseDuration("measure-blocks", phaseStartedAt);
|
|
317
|
+
const buildNoteOptions = () => {
|
|
318
|
+
const noteOptions = { measureBlocks };
|
|
319
|
+
if (flowOpts.styles) noteOptions.styles = flowOpts.styles;
|
|
320
|
+
if (flowOpts.defaultSize !== void 0) noteOptions.defaultSize = flowOpts.defaultSize;
|
|
321
|
+
if (_theme !== void 0) noteOptions.theme = _theme;
|
|
322
|
+
noteOptions.fontAlternates = fontAlternates;
|
|
323
|
+
if (defaultTabStop !== void 0) noteOptions.defaultTabStopTwips = defaultTabStop;
|
|
324
|
+
if (flowOpts.lineBreakRules) noteOptions.lineBreakRules = flowOpts.lineBreakRules;
|
|
325
|
+
if (flowOpts.justificationCompatibility) noteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
|
|
326
|
+
if (flowOpts.tableIndentCompatibility) noteOptions.tableIndentCompatibility = flowOpts.tableIndentCompatibility;
|
|
327
|
+
if (flowOpts.automaticHyphenation) noteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
|
|
328
|
+
return noteOptions;
|
|
329
|
+
};
|
|
330
|
+
const endnoteAreas = documentEndnotes && endnoteDisplayNumbers && endnoteTexts ? prepareEndnoteAreas({
|
|
331
|
+
blocks: newBlocks,
|
|
332
|
+
endnotes: documentEndnotes,
|
|
333
|
+
displayNumbers: endnoteDisplayNumbers,
|
|
334
|
+
displayTexts: endnoteTexts,
|
|
335
|
+
position: endnotePosition,
|
|
336
|
+
sections: sectionPropertiesForMargins,
|
|
337
|
+
options: buildNoteOptions()
|
|
338
|
+
}) : void 0;
|
|
339
|
+
const layoutWithNoteAreas = (measures, nextLayoutOpts) => {
|
|
340
|
+
if (endnoteAreas === void 0) return layoutDocument(newBlocks, measures, nextLayoutOpts);
|
|
341
|
+
const flow = spliceEndnoteAreas(newBlocks, measures, endnoteAreas);
|
|
342
|
+
return layoutDocument(flow.blocks, flow.measures, {
|
|
343
|
+
...nextLayoutOpts,
|
|
344
|
+
noteAreas: endnoteAreas.noteAreas
|
|
345
|
+
});
|
|
346
|
+
};
|
|
305
347
|
phaseStartedAt = performance.now();
|
|
306
348
|
let newLayout;
|
|
307
349
|
let pageFootnoteMap = /* @__PURE__ */ new Map();
|
|
@@ -338,29 +380,17 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
338
380
|
const layoutOpts = buildLayoutOpts();
|
|
339
381
|
let layoutOptsUsed = layoutOpts;
|
|
340
382
|
if (hasFootnotes) {
|
|
341
|
-
footnoteContentMap = buildFootnoteContentMap(documentFootnotes, footnoteRefs, contentWidth, (
|
|
342
|
-
const footnoteOptions = { measureBlocks };
|
|
343
|
-
if (flowOpts.styles) footnoteOptions.styles = flowOpts.styles;
|
|
344
|
-
if (flowOpts.defaultSize !== void 0) footnoteOptions.defaultSize = flowOpts.defaultSize;
|
|
345
|
-
if (_theme !== void 0) footnoteOptions.theme = _theme;
|
|
346
|
-
footnoteOptions.fontAlternates = fontAlternates;
|
|
347
|
-
if (defaultTabStop !== void 0) footnoteOptions.defaultTabStopTwips = defaultTabStop;
|
|
348
|
-
if (flowOpts.lineBreakRules) footnoteOptions.lineBreakRules = flowOpts.lineBreakRules;
|
|
349
|
-
if (flowOpts.justificationCompatibility) footnoteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
|
|
350
|
-
if (flowOpts.tableIndentCompatibility) footnoteOptions.tableIndentCompatibility = flowOpts.tableIndentCompatibility;
|
|
351
|
-
if (flowOpts.automaticHyphenation) footnoteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
|
|
352
|
-
return footnoteOptions;
|
|
353
|
-
})());
|
|
383
|
+
footnoteContentMap = buildFootnoteContentMap(documentFootnotes, footnoteRefs, contentWidth, buildNoteOptions());
|
|
354
384
|
const footnoteHeightById = /* @__PURE__ */ new Map();
|
|
355
385
|
for (const [id, content] of footnoteContentMap) footnoteHeightById.set(id, content.height + 0);
|
|
356
386
|
layoutOptsUsed = {
|
|
357
387
|
...layoutOpts,
|
|
358
388
|
footnoteHeightById
|
|
359
389
|
};
|
|
360
|
-
newLayout =
|
|
390
|
+
newLayout = layoutWithNoteAreas(newMeasures, layoutOptsUsed);
|
|
361
391
|
pageFootnoteMap = /* @__PURE__ */ new Map();
|
|
362
392
|
for (const page of newLayout.pages) if (page.footnoteIds && page.footnoteIds.length > 0) pageFootnoteMap.set(page.number, page.footnoteIds);
|
|
363
|
-
} else newLayout =
|
|
393
|
+
} else newLayout = layoutWithNoteAreas(newMeasures, layoutOpts);
|
|
364
394
|
const rebuildFootnotePageMap = () => {
|
|
365
395
|
pageFootnoteMap = /* @__PURE__ */ new Map();
|
|
366
396
|
for (const page of newLayout.pages) if (page.footnoteIds && page.footnoteIds.length > 0) pageFootnoteMap.set(page.number, page.footnoteIds);
|
|
@@ -376,7 +406,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
376
406
|
};
|
|
377
407
|
const relayoutWithCurrentMeasures = (nextLayoutOpts) => {
|
|
378
408
|
layoutOptsUsed = withFootnoteHeights(nextLayoutOpts);
|
|
379
|
-
newLayout =
|
|
409
|
+
newLayout = layoutWithNoteAreas(newMeasures, layoutOptsUsed);
|
|
380
410
|
if (hasFootnotes) rebuildFootnotePageMap();
|
|
381
411
|
};
|
|
382
412
|
const stabilizeFieldWidths = () => {
|
|
@@ -473,6 +503,18 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
473
503
|
measure
|
|
474
504
|
});
|
|
475
505
|
}
|
|
506
|
+
for (const area of endnoteAreas?.areas ?? []) for (const [index, block] of area.blocks.entries()) {
|
|
507
|
+
const measure = area.measures[index];
|
|
508
|
+
if (!measure) continue;
|
|
509
|
+
const noteStory = endnoteAreas?.noteStoryByBlockId.get(String(block.id));
|
|
510
|
+
blockLookup.set(String(block.id), {
|
|
511
|
+
block,
|
|
512
|
+
measure,
|
|
513
|
+
...noteStory === void 0 ? {} : { noteStory }
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
const continuationSeparator = endnoteAreas?.noteAreas.continuationSeparator;
|
|
517
|
+
if (continuationSeparator) blockLookup.set(String(continuationSeparator.block.id), continuationSeparator);
|
|
476
518
|
outcome.blockLookup = blockLookup;
|
|
477
519
|
const footnotesByPage = hasFootnotes ? buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, document) : void 0;
|
|
478
520
|
const renderOpts = {
|
|
@@ -5,7 +5,7 @@ import { collectFloatingImages, pageGeometryOf } from "./floatingImages.js";
|
|
|
5
5
|
import { FontTable } from "./fontTable.js";
|
|
6
6
|
import { paintPageFurniture } from "./furniture.js";
|
|
7
7
|
import { ImageTable, paintImageFragment } from "./imagePrimitives.js";
|
|
8
|
-
import { paintColumnSeparators, paintPageBackground } from "./pageFurniture.js";
|
|
8
|
+
import { paintColumnSeparators, paintFlowedNoteSeparators, paintPageBackground } from "./pageFurniture.js";
|
|
9
9
|
import { paintParagraphFragment } from "./paragraphPrimitives.js";
|
|
10
10
|
import { blockRegion, createPageComposer } from "./regions.js";
|
|
11
11
|
import { paintTableFragment } from "./tablePrimitives.js";
|
|
@@ -231,24 +231,51 @@ const buildPage = ({ page, pageIndex, totalPages, blockLookup, pageBackground, b
|
|
|
231
231
|
unsupported.report(UNSUPPORTED_CONSTRUCT.missingBlock, pageIndex, `no block lookup entry for ${fragment.kind} fragment ${String(fragment.blockId)}`);
|
|
232
232
|
continue;
|
|
233
233
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
kind: FRAGMENT_REGION_KIND[fragment.kind],
|
|
237
|
-
context
|
|
238
|
-
}), () => {
|
|
239
|
-
paintFragment({
|
|
234
|
+
const paint = (fragmentContext) => {
|
|
235
|
+
composer.region(blockRegion({
|
|
240
236
|
fragment,
|
|
241
|
-
|
|
242
|
-
context
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
237
|
+
kind: FRAGMENT_REGION_KIND[fragment.kind],
|
|
238
|
+
context: fragmentContext
|
|
239
|
+
}), () => {
|
|
240
|
+
paintFragment({
|
|
241
|
+
fragment,
|
|
242
|
+
entry,
|
|
243
|
+
context: fragmentContext,
|
|
244
|
+
composer,
|
|
245
|
+
prevEntry: entries[index - 1],
|
|
246
|
+
nextEntry: entries[index + 1]
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
const noteStory = entry.noteStory;
|
|
251
|
+
if (noteStory === void 0) {
|
|
252
|
+
paint(context);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const story = {
|
|
256
|
+
kind: noteStory.kind,
|
|
257
|
+
id: noteStory.noteId
|
|
258
|
+
};
|
|
259
|
+
composer.region({
|
|
260
|
+
kind: HIT_REGION_KINDS.note,
|
|
261
|
+
rect: {
|
|
262
|
+
xPx: fragment.x,
|
|
263
|
+
yPx: fragment.y,
|
|
264
|
+
widthPx: fragment.width,
|
|
265
|
+
heightPx: fragment.height
|
|
266
|
+
},
|
|
267
|
+
model: { story }
|
|
268
|
+
}, () => {
|
|
269
|
+
paint({
|
|
270
|
+
...context,
|
|
271
|
+
story
|
|
246
272
|
});
|
|
247
273
|
});
|
|
248
274
|
}
|
|
249
275
|
});
|
|
250
276
|
composer.push(frontFloats);
|
|
251
277
|
composer.push(paintColumnSeparators(page));
|
|
278
|
+
composer.push(paintFlowedNoteSeparators(page));
|
|
252
279
|
above(composer);
|
|
253
280
|
return {
|
|
254
281
|
pageNumber: page.number,
|
|
@@ -11,6 +11,12 @@ declare const paintPageBackground: (page: Page, fill: DisplayColor) => DisplayPr
|
|
|
11
11
|
* never drew them.
|
|
12
12
|
*/
|
|
13
13
|
declare const paintColumnSeparators: (page: Page) => readonly DisplayPrimitive[];
|
|
14
|
+
/**
|
|
15
|
+
* The separator rules of a note area laid out in the body flow (endnotes): the
|
|
16
|
+
* paginator records where each `w:separator` / `w:continuationSeparator` mark
|
|
17
|
+
* landed, so like the column rules they are derivable from the `Layout` alone.
|
|
18
|
+
*/
|
|
19
|
+
declare const paintFlowedNoteSeparators: (page: Page) => readonly DisplayPrimitive[];
|
|
14
20
|
type FootnoteAreaPaintOptions = {
|
|
15
21
|
readonly composer: PageComposer;
|
|
16
22
|
readonly page: Page;
|
|
@@ -32,4 +38,4 @@ type FootnoteAreaPaintOptions = {
|
|
|
32
38
|
*/
|
|
33
39
|
declare const paintFootnoteArea: ({ composer, page, context, contentById }: FootnoteAreaPaintOptions) => void;
|
|
34
40
|
//#endregion
|
|
35
|
-
export { FootnoteAreaPaintOptions, paintColumnSeparators, paintFootnoteArea, paintPageBackground };
|
|
41
|
+
export { FootnoteAreaPaintOptions, paintColumnSeparators, paintFlowedNoteSeparators, paintFootnoteArea, paintPageBackground };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../../layout-engine/types.js";
|
|
1
|
+
import { NOTE_SEPARATOR_RULE_THICKNESS, NOTE_SEPARATOR_WIDTH_FRACTION } from "../../layout-engine/types.js";
|
|
2
2
|
import { calculateFootnoteAreaRenderHeight } from "../../layout-painter/renderPage.js";
|
|
3
3
|
import { HIT_REGION_KINDS } from "../primitives.js";
|
|
4
4
|
import { DOC_CANVAS_TEXT } from "./colors.js";
|
|
@@ -20,10 +20,8 @@ import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
|
|
|
20
20
|
*/
|
|
21
21
|
/** `renderPage.ts:2049`: a hairline in the canvas ink colour. */
|
|
22
22
|
const COLUMN_SEPARATOR_WIDTH_PX = .5;
|
|
23
|
-
/** `
|
|
24
|
-
const
|
|
25
|
-
const FOOTNOTE_RULE_WIDTH_FRACTION = .33;
|
|
26
|
-
const FOOTNOTE_RULE_MARGIN_PX = (12 - FOOTNOTE_RULE_THICKNESS_PX) / 2;
|
|
23
|
+
/** `renderFootnoteArea`: a hairline across a third of the column, centred in its 12px slot. */
|
|
24
|
+
const FOOTNOTE_RULE_MARGIN_PX = (12 - NOTE_SEPARATOR_RULE_THICKNESS) / 2;
|
|
27
25
|
const paintPageBackground = (page, fill) => ({
|
|
28
26
|
kind: "rect",
|
|
29
27
|
rect: {
|
|
@@ -63,6 +61,21 @@ const paintColumnSeparators = (page) => {
|
|
|
63
61
|
return primitives;
|
|
64
62
|
};
|
|
65
63
|
/**
|
|
64
|
+
* The separator rules of a note area laid out in the body flow (endnotes): the
|
|
65
|
+
* paginator records where each `w:separator` / `w:continuationSeparator` mark
|
|
66
|
+
* landed, so like the column rules they are derivable from the `Layout` alone.
|
|
67
|
+
*/
|
|
68
|
+
const paintFlowedNoteSeparators = (page) => (page.noteSeparators ?? []).map((rule) => ({
|
|
69
|
+
kind: "rect",
|
|
70
|
+
rect: {
|
|
71
|
+
xPx: rule.x,
|
|
72
|
+
yPx: rule.y,
|
|
73
|
+
widthPx: rule.width,
|
|
74
|
+
heightPx: NOTE_SEPARATOR_RULE_THICKNESS
|
|
75
|
+
},
|
|
76
|
+
fill: DOC_CANVAS_TEXT
|
|
77
|
+
}));
|
|
78
|
+
/**
|
|
66
79
|
* The footnote band at the foot of the body column: the separator rule, then
|
|
67
80
|
* one body per note the paginator put on this page.
|
|
68
81
|
*
|
|
@@ -98,8 +111,8 @@ const paintFootnoteArea = ({ composer, page, context, contentById }) => {
|
|
|
98
111
|
rect: {
|
|
99
112
|
xPx: page.margins.left,
|
|
100
113
|
yPx: areaTopPx + FOOTNOTE_RULE_MARGIN_PX,
|
|
101
|
-
widthPx: contentWidthPx *
|
|
102
|
-
heightPx:
|
|
114
|
+
widthPx: contentWidthPx * NOTE_SEPARATOR_WIDTH_FRACTION,
|
|
115
|
+
heightPx: NOTE_SEPARATOR_RULE_THICKNESS
|
|
103
116
|
},
|
|
104
117
|
fill: DOC_CANVAS_TEXT
|
|
105
118
|
}];
|
|
@@ -138,4 +151,4 @@ const paintFootnoteArea = ({ composer, page, context, contentById }) => {
|
|
|
138
151
|
}
|
|
139
152
|
};
|
|
140
153
|
//#endregion
|
|
141
|
-
export { paintColumnSeparators, paintFootnoteArea, paintPageBackground };
|
|
154
|
+
export { paintColumnSeparators, paintFlowedNoteSeparators, paintFootnoteArea, paintPageBackground };
|
|
@@ -6,7 +6,7 @@ import { countCompressibleSpaces, toPaintedText } from "../../layout-engine/meas
|
|
|
6
6
|
import { isFloatingImageRun } from "../../layout-engine/types.js";
|
|
7
7
|
import { resolveParagraphBorderHorizontalOutsets } from "../../layout-painter/borderStroke.js";
|
|
8
8
|
import { getAutomaticTextColorForBackground } from "../../layout-painter/documentColors.js";
|
|
9
|
-
import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, paragraphHasTrackedChanges, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
|
|
9
|
+
import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableListMarkerColor, getRenderableTextColor, paragraphHasTrackedChanges, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
|
|
10
10
|
import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
|
|
11
11
|
import { resolvePhysicalParagraphInlineLayout } from "../../utils/paragraphInlineLayout.js";
|
|
12
12
|
import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
|
|
@@ -368,7 +368,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
|
|
|
368
368
|
} else context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `run background ${background}`);
|
|
369
369
|
}
|
|
370
370
|
const font = context.fonts.intern({
|
|
371
|
-
fontFamily: style.fontFamily ?? "
|
|
371
|
+
fontFamily: style.fontFamily ?? "Times New Roman",
|
|
372
372
|
...style.alternateFontFamily === void 0 ? {} : { alternateFontFamily: style.alternateFontFamily },
|
|
373
373
|
...style.bold === void 0 ? {} : { bold: style.bold },
|
|
374
374
|
...style.italic === void 0 ? {} : { italic: style.italic },
|
|
@@ -729,6 +729,7 @@ const paintLine = ({ block, line, geometry, context, alignment, isRtl, isFirstLi
|
|
|
729
729
|
tabRegions
|
|
730
730
|
};
|
|
731
731
|
};
|
|
732
|
+
const parseMarkerColor = (color) => color === void 0 ? void 0 : parseDisplayColor(color);
|
|
732
733
|
const paintListMarker = ({ sink, block, context, paintXPx, baselineYPx, isRtl }) => {
|
|
733
734
|
const marker = block.attrs?.listMarker;
|
|
734
735
|
if (marker === void 0 || marker.length === 0) return;
|
|
@@ -742,7 +743,7 @@ const paintListMarker = ({ sink, block, context, paintXPx, baselineYPx, isRtl })
|
|
|
742
743
|
collapsed: false
|
|
743
744
|
});
|
|
744
745
|
const revision = block.attrs?.listMarkerRevision;
|
|
745
|
-
const color = revision ? trackedChangeColor(context.authorColors, revision.author, void 0) : DOC_CANVAS_TEXT;
|
|
746
|
+
const color = revision ? trackedChangeColor(context.authorColors, revision.author, void 0) : parseMarkerColor(getRenderableListMarkerColor(formatting.color)) ?? DOC_CANVAS_TEXT;
|
|
746
747
|
const font = context.fonts.intern({
|
|
747
748
|
fontFamily: formatting.fontFamily,
|
|
748
749
|
...formatting.alternateFontFamily === void 0 ? {} : { alternateFontFamily: formatting.alternateFontFamily },
|
|
@@ -813,7 +814,7 @@ const paintTab = ({ sink, context, runs, index, run, tabContext, layoutXPx, pain
|
|
|
813
814
|
collapsed: false
|
|
814
815
|
});
|
|
815
816
|
const font = context.fonts.intern({
|
|
816
|
-
fontFamily: style.fontFamily ?? "
|
|
817
|
+
fontFamily: style.fontFamily ?? "Times New Roman",
|
|
817
818
|
...style.bold === void 0 ? {} : { bold: style.bold },
|
|
818
819
|
...style.italic === void 0 ? {} : { italic: style.italic },
|
|
819
820
|
measureStyle: style
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createTableCellFlowState, placeTableCellBlock } from "../../layout-engine/measure/tableCellFlow.js";
|
|
2
|
-
import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../../layout-engine/measure/tableCellGrid.js";
|
|
2
|
+
import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt, getTableCellSpacingInsetsY } from "../../layout-engine/measure/tableCellGrid.js";
|
|
3
3
|
import { tableFragmentBottomBorders } from "../../layout-engine/measure/tableFragmentBorderGeometry.js";
|
|
4
4
|
import { resolveTableCellPadding } from "../../layout-engine/types.js";
|
|
5
5
|
import { cellTextRotationDegrees } from "../../layout-painter/renderTable.js";
|
|
@@ -253,8 +253,10 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
|
|
|
253
253
|
const placements = buildTableCellPlacements({
|
|
254
254
|
grid,
|
|
255
255
|
columnWidths: measure.columnWidths,
|
|
256
|
-
bidi: block.bidi === true
|
|
256
|
+
bidi: block.bidi === true,
|
|
257
|
+
cellSpacing: block.cellSpacing
|
|
257
258
|
});
|
|
259
|
+
const bordersSeparated = (block.cellSpacing ?? 0) > 0;
|
|
258
260
|
const rowTops = [0];
|
|
259
261
|
for (const rowMeasure of measure.rows) rowTops.push((rowTops.at(-1) ?? 0) + rowMeasure.height);
|
|
260
262
|
const paintRow = (rowIndex, rowYPx) => {
|
|
@@ -283,7 +285,9 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
|
|
|
283
285
|
if (!placement) continue;
|
|
284
286
|
const rowSpan = Math.max(1, Math.trunc(cell.rowSpan ?? 1));
|
|
285
287
|
const spanEnd = Math.min(rowTops.length - 1, rowIndex + rowSpan);
|
|
286
|
-
const
|
|
288
|
+
const slotHeightPx = spanEnd > rowIndex ? rowTops[spanEnd] - rowTops[rowIndex] : rowMeasure.height;
|
|
289
|
+
const spacing = getTableCellSpacingInsetsY(block.cellSpacing, rowIndex, rowSpan, block.rows.length);
|
|
290
|
+
const heightPx = Math.max(0, slotHeightPx - spacing.top - spacing.bottom);
|
|
287
291
|
const atLogicalStart = placement.sourceColumn === 0;
|
|
288
292
|
const atLogicalEnd = placement.sourceColumn + placement.columnSpan >= measure.columnWidths.length;
|
|
289
293
|
const isFirstColumn = block.bidi === true ? atLogicalEnd : atLogicalStart;
|
|
@@ -292,7 +296,7 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
|
|
|
292
296
|
const leftCell = getSourceCellAt(grid, rowIndex, leftNeighborColumn);
|
|
293
297
|
const box = {
|
|
294
298
|
xPx: xPx + placement.left,
|
|
295
|
-
yPx: rowYPx,
|
|
299
|
+
yPx: rowYPx + spacing.top,
|
|
296
300
|
widthPx: placement.width,
|
|
297
301
|
heightPx
|
|
298
302
|
};
|
|
@@ -312,9 +316,9 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
|
|
|
312
316
|
context,
|
|
313
317
|
paintTextBox,
|
|
314
318
|
sides: {
|
|
315
|
-
top: rowIndex === fromRow || !hasVisibleBorder(aboveCell?.borders?.bottom),
|
|
319
|
+
top: bordersSeparated || rowIndex === fromRow || !hasVisibleBorder(aboveCell?.borders?.bottom),
|
|
316
320
|
bottom: true,
|
|
317
|
-
left: isFirstColumn || !hasVisibleBorder(leftCell?.borders?.right),
|
|
321
|
+
left: bordersSeparated || isFirstColumn || !hasVisibleBorder(leftCell?.borders?.right),
|
|
318
322
|
right: true
|
|
319
323
|
}
|
|
320
324
|
});
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { modelledAttributeNames } from "./propertyElementAttributes.js";
|
|
2
2
|
import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
|
|
3
|
+
import { XML_NAMESPACE_URI } from "./xmlNamespaceContext.js";
|
|
3
4
|
import { getLocalName, resolveAttributeNamespaceUri } from "./xmlParser.js";
|
|
4
5
|
import { TaggedError } from "better-result";
|
|
5
6
|
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
6
7
|
//#region src/docx/attributeRemainder.ts
|
|
7
|
-
/**
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Namespace URI to the prefix a rebuilt part binds for it.
|
|
10
|
+
*
|
|
11
|
+
* `xml` is reserved rather than declared — {@link OOXML_NAMESPACES} excludes
|
|
12
|
+
* it because a rebuilt part must never write `xmlns:xml` — so it is added
|
|
13
|
+
* here on its own: the remainder still has to spell `xml:space`, `xml:lang`
|
|
14
|
+
* and `xml:id` back, or the attribute is written unprefixed instead of dropped.
|
|
15
|
+
*/
|
|
16
|
+
const CANONICAL_PREFIX = new Map([...Object.entries(OOXML_NAMESPACES).map(([prefix, { uri }]) => [uri, prefix]), [XML_NAMESPACE_URI, "xml"]]);
|
|
9
17
|
const XML_LOCAL_NAME = /^[\p{L}_][\p{L}\p{M}\p{N}._\-\u{00B7}\u{203F}-\u{2040}]*$/u;
|
|
10
18
|
var InvalidPreservedAttributeError = class extends TaggedError("InvalidPreservedAttributeError") {};
|
|
11
19
|
/** Whether an attribute remainder can be emitted under a bound canonical name. */
|
|
@@ -2,12 +2,14 @@ import { document_d_exports } from "../types/document.js";
|
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
3
|
import { ParseContext } from "./parseContext.js";
|
|
4
4
|
import { XmlElement } from "./xmlParser.js";
|
|
5
|
+
import { PreviewLedger } from "./previewBudget.js";
|
|
5
6
|
import { StyleMap } from "./styleParser.js";
|
|
6
7
|
//#region src/docx/blockContentParser.d.ts
|
|
7
8
|
type ParseBlockContentOptions = {
|
|
8
9
|
inHeaderFooter?: boolean;
|
|
9
10
|
rootXmlns?: Record<string, string>;
|
|
10
11
|
context?: ParseContext | undefined;
|
|
12
|
+
previews?: PreviewLedger;
|
|
11
13
|
};
|
|
12
14
|
declare const parseBlockContent: (parent: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null, options?: ParseBlockContentOptions) => document_d_exports.BlockContent[];
|
|
13
15
|
//#endregion
|