docxodus 9.7.0 → 9.8.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/LICENSE +22 -0
- package/README.md +0 -1
- package/dist/editor.bundle.js +290 -76
- package/dist/editor.d.ts +4 -4
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +55 -8
- package/dist/editor.js.map +1 -1
- package/dist/embed.bundle.js +290 -76
- package/dist/embed.iife.js +290 -76
- package/dist/page-geometry.d.ts +50 -3
- package/dist/page-geometry.d.ts.map +1 -1
- package/dist/page-geometry.js +63 -6
- package/dist/page-geometry.js.map +1 -1
- package/dist/pagination.bundle.js +253 -68
- package/dist/pagination.d.ts +33 -8
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +198 -78
- package/dist/pagination.js.map +1 -1
- package/dist/wasm/_framework/Docxodus.wasm +0 -0
- package/dist/wasm/_framework/Docxodus.wasm.br +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm.br +0 -0
- package/dist/wasm/_framework/System.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.boot.js +6 -6
- package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
- package/package.json +13 -5
- package/dist/wasm/index.html +0 -238
- package/dist/wasm/main.js +0 -26
package/dist/page-geometry.js
CHANGED
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
export const DEFAULT_PAGE_WIDTH = 612;
|
|
19
19
|
export const DEFAULT_PAGE_HEIGHT = 792;
|
|
20
20
|
export const DEFAULT_MARGIN = 72; // 1 inch
|
|
21
|
-
/** Default header/footer distance (0.5 inch). */
|
|
22
|
-
export const
|
|
21
|
+
/** Default header/footer distance from the paper edge (0.5 inch). */
|
|
22
|
+
export const DEFAULT_HEADER_FOOTER_DISTANCE = 36;
|
|
23
|
+
/** @deprecated Misnamed alias of {@link DEFAULT_HEADER_FOOTER_DISTANCE}. */
|
|
24
|
+
export const DEFAULT_HEADER_FOOTER_HEIGHT = DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
23
25
|
/** Converts pixels to points (assuming 96 DPI screen). */
|
|
24
26
|
export function pxToPt(px) {
|
|
25
27
|
return px * 0.75; // 72 points / 96 pixels
|
|
@@ -38,8 +40,10 @@ export function parseSectionDimensions(section) {
|
|
|
38
40
|
const marginRight = parseFloat(section.dataset.marginRight || "") || DEFAULT_MARGIN;
|
|
39
41
|
const marginBottom = parseFloat(section.dataset.marginBottom || "") || DEFAULT_MARGIN;
|
|
40
42
|
const marginLeft = parseFloat(section.dataset.marginLeft || "") || DEFAULT_MARGIN;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
// `data-header-height`/`data-footer-height` carry `w:pgMar/@w:header` and `@w:footer`, which
|
|
44
|
+
// are distances from the paper edge — the attribute names predate that being understood.
|
|
45
|
+
const headerDistance = parseFloat(section.dataset.headerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
46
|
+
const footerDistance = parseFloat(section.dataset.footerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
43
47
|
return {
|
|
44
48
|
pageWidth,
|
|
45
49
|
pageHeight,
|
|
@@ -49,8 +53,61 @@ export function parseSectionDimensions(section) {
|
|
|
49
53
|
marginRight,
|
|
50
54
|
marginBottom,
|
|
51
55
|
marginLeft,
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
headerDistance,
|
|
57
|
+
footerDistance,
|
|
58
|
+
headerHeight: headerDistance,
|
|
59
|
+
footerHeight: footerDistance,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A body band this short cannot hold a single line, and a page that can hold nothing sends
|
|
64
|
+
* every block down the oversized-block path. Running content may push the body — Word does
|
|
65
|
+
* that — but it may not delete it, so a pathological header/footer gives this much back.
|
|
66
|
+
*/
|
|
67
|
+
export const MIN_BODY_BAND_PT = 12;
|
|
68
|
+
/**
|
|
69
|
+
* Word's page band model.
|
|
70
|
+
*
|
|
71
|
+
* `w:header`/`w:footer` are DISTANCES from the paper edge to the running content, and
|
|
72
|
+
* `w:top`/`w:bottom` are distances from the paper edge to the body text — four independent
|
|
73
|
+
* numbers, not two nested boxes. The header is laid out from `headerDistance` downward and
|
|
74
|
+
* the footer from `footerDistance` upward; the body then starts at the top margin unless the
|
|
75
|
+
* header has already run past it, and ends at the bottom margin unless the footer has
|
|
76
|
+
* already climbed above it.
|
|
77
|
+
*
|
|
78
|
+
* Anchoring the bands to the margins instead — header bottom-aligned to `marginTop`, footer
|
|
79
|
+
* top-aligned to `pageHeight - marginBottom` — collapses both toward the body by exactly
|
|
80
|
+
* `margin - distance`, which is what this function replaced.
|
|
81
|
+
*/
|
|
82
|
+
export function resolvePageBands(dims, headerContentHeight, footerContentHeight) {
|
|
83
|
+
const headerTop = dims.headerDistance;
|
|
84
|
+
const footerBottom = dims.pageHeight - dims.footerDistance;
|
|
85
|
+
// A page with NO running story has nothing below the paper edge to push the body: the
|
|
86
|
+
// distance alone reserves no space. (Word's own empty header is still a story — one empty
|
|
87
|
+
// paragraph with a real line height — so zero here means absent, not blank.)
|
|
88
|
+
const headerReach = headerContentHeight > 0 ? headerTop + headerContentHeight : 0;
|
|
89
|
+
const footerReach = footerContentHeight > 0 ? footerBottom - footerContentHeight : dims.pageHeight;
|
|
90
|
+
let bodyTop = Math.max(dims.marginTop, headerReach);
|
|
91
|
+
let bodyBottom = Math.min(dims.pageHeight - dims.marginBottom, footerReach);
|
|
92
|
+
// Hand back whatever the bands over-claimed, in proportion to how far each grew past its
|
|
93
|
+
// own margin, so a tall header does not silently consume the whole page.
|
|
94
|
+
const shortfall = MIN_BODY_BAND_PT - (bodyBottom - bodyTop);
|
|
95
|
+
if (shortfall > 0) {
|
|
96
|
+
const headerGrowth = bodyTop - dims.marginTop;
|
|
97
|
+
const footerGrowth = dims.pageHeight - dims.marginBottom - bodyBottom;
|
|
98
|
+
const growth = headerGrowth + footerGrowth;
|
|
99
|
+
if (growth > 0) {
|
|
100
|
+
bodyTop -= (shortfall * headerGrowth) / growth;
|
|
101
|
+
bodyBottom += (shortfall * footerGrowth) / growth;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
headerTop,
|
|
106
|
+
headerHeight: Math.max(0, Math.min(headerContentHeight, bodyTop - headerTop)),
|
|
107
|
+
bodyTop,
|
|
108
|
+
bodyHeight: Math.max(0, bodyBottom - bodyTop),
|
|
109
|
+
footerTop: footerBottom - Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),
|
|
110
|
+
footerHeight: Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),
|
|
54
111
|
};
|
|
55
112
|
}
|
|
56
113
|
/** Every section wrapper under `root`, or `root` itself when the render stamped none. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-geometry.js","sourceRoot":"","sources":["../src/page-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"page-geometry.js","sourceRoot":"","sources":["../src/page-geometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,7 +63,7 @@ var DocxodusPagination = (() => {
|
|
|
63
63
|
var DEFAULT_PAGE_WIDTH = 612;
|
|
64
64
|
var DEFAULT_PAGE_HEIGHT = 792;
|
|
65
65
|
var DEFAULT_MARGIN = 72;
|
|
66
|
-
var
|
|
66
|
+
var DEFAULT_HEADER_FOOTER_DISTANCE = 36;
|
|
67
67
|
function pxToPt(px) {
|
|
68
68
|
return px * 0.75;
|
|
69
69
|
}
|
|
@@ -79,8 +79,8 @@ var DocxodusPagination = (() => {
|
|
|
79
79
|
const marginRight = parseFloat(section.dataset.marginRight || "") || DEFAULT_MARGIN;
|
|
80
80
|
const marginBottom = parseFloat(section.dataset.marginBottom || "") || DEFAULT_MARGIN;
|
|
81
81
|
const marginLeft = parseFloat(section.dataset.marginLeft || "") || DEFAULT_MARGIN;
|
|
82
|
-
const
|
|
83
|
-
const
|
|
82
|
+
const headerDistance = parseFloat(section.dataset.headerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
83
|
+
const footerDistance = parseFloat(section.dataset.footerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
84
84
|
return {
|
|
85
85
|
pageWidth,
|
|
86
86
|
pageHeight,
|
|
@@ -90,8 +90,37 @@ var DocxodusPagination = (() => {
|
|
|
90
90
|
marginRight,
|
|
91
91
|
marginBottom,
|
|
92
92
|
marginLeft,
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
headerDistance,
|
|
94
|
+
footerDistance,
|
|
95
|
+
headerHeight: headerDistance,
|
|
96
|
+
footerHeight: footerDistance
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
var MIN_BODY_BAND_PT = 12;
|
|
100
|
+
function resolvePageBands(dims, headerContentHeight, footerContentHeight) {
|
|
101
|
+
const headerTop = dims.headerDistance;
|
|
102
|
+
const footerBottom = dims.pageHeight - dims.footerDistance;
|
|
103
|
+
const headerReach = headerContentHeight > 0 ? headerTop + headerContentHeight : 0;
|
|
104
|
+
const footerReach = footerContentHeight > 0 ? footerBottom - footerContentHeight : dims.pageHeight;
|
|
105
|
+
let bodyTop = Math.max(dims.marginTop, headerReach);
|
|
106
|
+
let bodyBottom = Math.min(dims.pageHeight - dims.marginBottom, footerReach);
|
|
107
|
+
const shortfall = MIN_BODY_BAND_PT - (bodyBottom - bodyTop);
|
|
108
|
+
if (shortfall > 0) {
|
|
109
|
+
const headerGrowth = bodyTop - dims.marginTop;
|
|
110
|
+
const footerGrowth = dims.pageHeight - dims.marginBottom - bodyBottom;
|
|
111
|
+
const growth = headerGrowth + footerGrowth;
|
|
112
|
+
if (growth > 0) {
|
|
113
|
+
bodyTop -= shortfall * headerGrowth / growth;
|
|
114
|
+
bodyBottom += shortfall * footerGrowth / growth;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
headerTop,
|
|
119
|
+
headerHeight: Math.max(0, Math.min(headerContentHeight, bodyTop - headerTop)),
|
|
120
|
+
bodyTop,
|
|
121
|
+
bodyHeight: Math.max(0, bodyBottom - bodyTop),
|
|
122
|
+
footerTop: footerBottom - Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),
|
|
123
|
+
footerHeight: Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom))
|
|
95
124
|
};
|
|
96
125
|
}
|
|
97
126
|
|
|
@@ -336,9 +365,9 @@ var DocxodusPagination = (() => {
|
|
|
336
365
|
*/
|
|
337
366
|
smallestEffectiveContentHeight(dims, sectionIndex) {
|
|
338
367
|
return Math.min(
|
|
339
|
-
this.
|
|
340
|
-
this.
|
|
341
|
-
this.
|
|
368
|
+
this.getPageBands(dims, sectionIndex, 1, 1).bodyHeight,
|
|
369
|
+
this.getPageBands(dims, sectionIndex, 2, 1).bodyHeight,
|
|
370
|
+
this.getPageBands(dims, sectionIndex, 2, 2).bodyHeight
|
|
342
371
|
);
|
|
343
372
|
}
|
|
344
373
|
/**
|
|
@@ -862,7 +891,7 @@ var DocxodusPagination = (() => {
|
|
|
862
891
|
/**
|
|
863
892
|
* Adds footnotes to a page container, including continuation content.
|
|
864
893
|
*/
|
|
865
|
-
addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes) {
|
|
894
|
+
addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes) {
|
|
866
895
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
867
896
|
if (footnoteIds.length === 0 && !hasContinuation) {
|
|
868
897
|
return;
|
|
@@ -873,12 +902,12 @@ var DocxodusPagination = (() => {
|
|
|
873
902
|
const partialFootnoteIds = new Set(partialFootnotes?.map((p) => p.footnoteId) || []);
|
|
874
903
|
const maxFootnoteHeight = Math.min(
|
|
875
904
|
footnoteHeight,
|
|
876
|
-
|
|
905
|
+
bands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO
|
|
877
906
|
);
|
|
878
907
|
const footnotesDiv = document.createElement("div");
|
|
879
908
|
footnotesDiv.className = `${this.cssPrefix}footnotes`;
|
|
880
909
|
footnotesDiv.style.position = "absolute";
|
|
881
|
-
footnotesDiv.style.bottom = `${dims.
|
|
910
|
+
footnotesDiv.style.bottom = `${dims.pageHeight - (bands.bodyTop + bands.bodyHeight)}pt`;
|
|
882
911
|
footnotesDiv.style.left = `${dims.marginLeft}pt`;
|
|
883
912
|
footnotesDiv.style.width = `${dims.contentWidth}pt`;
|
|
884
913
|
footnotesDiv.style.boxSizing = "border-box";
|
|
@@ -952,50 +981,51 @@ var DocxodusPagination = (() => {
|
|
|
952
981
|
return sectionHf.footerDefault;
|
|
953
982
|
}
|
|
954
983
|
/**
|
|
955
|
-
*
|
|
956
|
-
*
|
|
957
|
-
*
|
|
958
|
-
*
|
|
959
|
-
*
|
|
984
|
+
* The header, body, and footer bands for one page position.
|
|
985
|
+
*
|
|
986
|
+
* The single owner of "where does anything sit vertically on this page" — placement in
|
|
987
|
+
* {@link createPage}, the body budget the flow loop spends, and the note area's anchor all
|
|
988
|
+
* read it, so those three cannot disagree about where the body ends.
|
|
989
|
+
*
|
|
990
|
+
* Deterministic: it depends only on the section's page setup and the registry's pre-measured
|
|
991
|
+
* story heights, never on the page's content, which is what keeps it lazy-loading compatible.
|
|
960
992
|
*/
|
|
961
|
-
|
|
993
|
+
getPageBands(dims, sectionIndex, pageInSection, globalPageNumber) {
|
|
962
994
|
const sectionHf = this.hfRegistry.get(sectionIndex);
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
const headerExpansion = headerHeight - dims.marginTop;
|
|
992
|
-
const footerExpansion = footerHeight - dims.marginBottom;
|
|
993
|
-
const contentHeight = dims.contentHeight - headerExpansion - footerExpansion;
|
|
994
|
-
return { headerHeight, footerHeight, contentHeight };
|
|
995
|
+
return resolvePageBands(
|
|
996
|
+
dims,
|
|
997
|
+
this.selectStoryHeight(
|
|
998
|
+
sectionHf?.headerFirstHeight,
|
|
999
|
+
sectionHf?.headerEvenHeight,
|
|
1000
|
+
sectionHf?.headerDefaultHeight,
|
|
1001
|
+
pageInSection,
|
|
1002
|
+
globalPageNumber
|
|
1003
|
+
),
|
|
1004
|
+
this.selectStoryHeight(
|
|
1005
|
+
sectionHf?.footerFirstHeight,
|
|
1006
|
+
sectionHf?.footerEvenHeight,
|
|
1007
|
+
sectionHf?.footerDefaultHeight,
|
|
1008
|
+
pageInSection,
|
|
1009
|
+
globalPageNumber
|
|
1010
|
+
)
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* The measured height of the running story this page position selects, mirroring
|
|
1015
|
+
* {@link selectHeader}/{@link selectFooter}. Zero when the page has no such story.
|
|
1016
|
+
*/
|
|
1017
|
+
selectStoryHeight(first, even, fallback, pageInSection, globalPageNumber) {
|
|
1018
|
+
if (pageInSection === 1 && first != null) return first;
|
|
1019
|
+
if (globalPageNumber % 2 === 0 && even != null) return even;
|
|
1020
|
+
return fallback ?? 0;
|
|
995
1021
|
}
|
|
996
1022
|
/**
|
|
997
1023
|
* Measures the content height of a header or footer element.
|
|
998
|
-
*
|
|
1024
|
+
*
|
|
1025
|
+
* This is what tells {@link resolvePageBands} whether the story stays inside its margin or
|
|
1026
|
+
* pushes the body, so it must measure the story ALONE — any padding added here would have to
|
|
1027
|
+
* be added to the rendered band too, and the two drifting apart is exactly how a header
|
|
1028
|
+
* silently starts overlapping body text.
|
|
999
1029
|
*/
|
|
1000
1030
|
measureHeaderFooterHeight(source, contentWidth) {
|
|
1001
1031
|
const measureContainer = document.createElement("div");
|
|
@@ -1003,7 +1033,6 @@ var DocxodusPagination = (() => {
|
|
|
1003
1033
|
measureContainer.style.visibility = "hidden";
|
|
1004
1034
|
measureContainer.style.width = `${contentWidth}pt`;
|
|
1005
1035
|
measureContainer.style.left = "-9999px";
|
|
1006
|
-
measureContainer.style.paddingBottom = "4pt";
|
|
1007
1036
|
for (const child of Array.from(source.childNodes)) {
|
|
1008
1037
|
measureContainer.appendChild(child.cloneNode(true));
|
|
1009
1038
|
}
|
|
@@ -1023,7 +1052,7 @@ var DocxodusPagination = (() => {
|
|
|
1023
1052
|
let currentContent = [];
|
|
1024
1053
|
let pageNumber = startPageNumber;
|
|
1025
1054
|
let pageInSection = 1;
|
|
1026
|
-
let {
|
|
1055
|
+
let { bodyHeight: effectiveContentHeight } = this.getPageBands(
|
|
1027
1056
|
dims,
|
|
1028
1057
|
sectionIndex,
|
|
1029
1058
|
pageInSection,
|
|
@@ -1058,8 +1087,8 @@ var DocxodusPagination = (() => {
|
|
|
1058
1087
|
pageNumber++;
|
|
1059
1088
|
pageInSection++;
|
|
1060
1089
|
currentContent = [];
|
|
1061
|
-
const
|
|
1062
|
-
effectiveContentHeight =
|
|
1090
|
+
const newBands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
1091
|
+
effectiveContentHeight = newBands.bodyHeight;
|
|
1063
1092
|
remainingHeight = effectiveContentHeight;
|
|
1064
1093
|
prevMarginBottomPt = 0;
|
|
1065
1094
|
currentFootnoteIds = [];
|
|
@@ -1121,7 +1150,7 @@ var DocxodusPagination = (() => {
|
|
|
1121
1150
|
) + additionalChainFootnoteHeight;
|
|
1122
1151
|
const currentAvailableHeight = remainingHeight - currentFootnoteHeight;
|
|
1123
1152
|
if (currentChainHeight > currentAvailableHeight) {
|
|
1124
|
-
const
|
|
1153
|
+
const nextPageBands = this.getPageBands(
|
|
1125
1154
|
dims,
|
|
1126
1155
|
sectionIndex,
|
|
1127
1156
|
pageInSection + 1,
|
|
@@ -1137,7 +1166,7 @@ var DocxodusPagination = (() => {
|
|
|
1137
1166
|
dims.contentWidth,
|
|
1138
1167
|
nextPageContinuation
|
|
1139
1168
|
);
|
|
1140
|
-
if (freshChainBodyHeight + freshChainFootnoteHeight <=
|
|
1169
|
+
if (freshChainBodyHeight + freshChainFootnoteHeight <= nextPageBands.bodyHeight) {
|
|
1141
1170
|
finishPage();
|
|
1142
1171
|
}
|
|
1143
1172
|
}
|
|
@@ -1306,6 +1335,161 @@ var DocxodusPagination = (() => {
|
|
|
1306
1335
|
if (el.getAttribute("contenteditable") !== null) el.setAttribute("contenteditable", "false");
|
|
1307
1336
|
}
|
|
1308
1337
|
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Resolves floating DrawingML objects after their anchor paragraphs have landed on a page.
|
|
1340
|
+
*
|
|
1341
|
+
* The converter deliberately carries the OOXML bases and offsets as data instead of flattening
|
|
1342
|
+
* them into CSS: page/margin/column bases belong to the page, while paragraph/line/character
|
|
1343
|
+
* bases belong to the laid-out anchor. Once both coordinate systems exist, promote the object
|
|
1344
|
+
* from the clipped text column into the page box and position it in one shared point space.
|
|
1345
|
+
*/
|
|
1346
|
+
positionDrawingAnchors(pageBox, contentArea, dims, pageNumber) {
|
|
1347
|
+
const anchors = Array.from(
|
|
1348
|
+
contentArea.querySelectorAll('[data-docx-drawing-anchor="true"]')
|
|
1349
|
+
);
|
|
1350
|
+
if (anchors.length === 0) return;
|
|
1351
|
+
const pageRect = pageBox.getBoundingClientRect();
|
|
1352
|
+
const pixelsPerPoint = pageRect.width / dims.pageWidth;
|
|
1353
|
+
if (!(pixelsPerPoint > 0)) return;
|
|
1354
|
+
for (const anchor of anchors) {
|
|
1355
|
+
const staticRect = anchor.getBoundingClientRect();
|
|
1356
|
+
const paragraph = anchor.closest("p, h1, h2, h3, h4, h5, h6");
|
|
1357
|
+
const paragraphRect = paragraph?.getBoundingClientRect() ?? staticRect;
|
|
1358
|
+
const toPageX = (x) => (x - pageRect.left) / pixelsPerPoint;
|
|
1359
|
+
const toPageY = (y) => (y - pageRect.top) / pixelsPerPoint;
|
|
1360
|
+
const context = {
|
|
1361
|
+
staticLeft: toPageX(staticRect.left),
|
|
1362
|
+
staticTop: toPageY(staticRect.top),
|
|
1363
|
+
lineHeight: paragraph ? (parseFloat(getComputedStyle(paragraph).lineHeight) || staticRect.height) / pixelsPerPoint : staticRect.height / pixelsPerPoint,
|
|
1364
|
+
paragraphLeft: toPageX(paragraphRect.left),
|
|
1365
|
+
paragraphTop: toPageY(paragraphRect.top),
|
|
1366
|
+
paragraphWidth: paragraphRect.width / pixelsPerPoint,
|
|
1367
|
+
paragraphHeight: paragraphRect.height / pixelsPerPoint
|
|
1368
|
+
};
|
|
1369
|
+
const widthReference = this.horizontalAnchorReference(
|
|
1370
|
+
anchor.getAttribute("data-docx-anchor-width-relative") ?? "margin",
|
|
1371
|
+
dims,
|
|
1372
|
+
pageNumber,
|
|
1373
|
+
context
|
|
1374
|
+
);
|
|
1375
|
+
const widthPercent = this.anchorNumber(anchor, "width-percent");
|
|
1376
|
+
if (widthPercent !== void 0) {
|
|
1377
|
+
anchor.style.width = `${widthReference.size * widthPercent / 100}pt`;
|
|
1378
|
+
}
|
|
1379
|
+
const heightReference = this.verticalAnchorReference(
|
|
1380
|
+
anchor.getAttribute("data-docx-anchor-height-relative") ?? "margin",
|
|
1381
|
+
dims,
|
|
1382
|
+
pageNumber,
|
|
1383
|
+
context
|
|
1384
|
+
);
|
|
1385
|
+
const heightPercent = this.anchorNumber(anchor, "height-percent");
|
|
1386
|
+
if (heightPercent !== void 0 && anchor.dataset.docxAnchorAutofit !== "true") {
|
|
1387
|
+
anchor.style.height = `${heightReference.size * heightPercent / 100}pt`;
|
|
1388
|
+
}
|
|
1389
|
+
const sizedRect = anchor.getBoundingClientRect();
|
|
1390
|
+
const width = sizedRect.width / pixelsPerPoint;
|
|
1391
|
+
const height = sizedRect.height / pixelsPerPoint;
|
|
1392
|
+
const horizontal = this.horizontalAnchorReference(
|
|
1393
|
+
anchor.getAttribute("data-docx-anchor-h-relative") ?? "column",
|
|
1394
|
+
dims,
|
|
1395
|
+
pageNumber,
|
|
1396
|
+
context
|
|
1397
|
+
);
|
|
1398
|
+
const vertical = this.verticalAnchorReference(
|
|
1399
|
+
anchor.getAttribute("data-docx-anchor-v-relative") ?? "paragraph",
|
|
1400
|
+
dims,
|
|
1401
|
+
pageNumber,
|
|
1402
|
+
context
|
|
1403
|
+
);
|
|
1404
|
+
const left = this.resolveAnchorAxis(
|
|
1405
|
+
horizontal,
|
|
1406
|
+
width,
|
|
1407
|
+
anchor.getAttribute("data-docx-anchor-h-align"),
|
|
1408
|
+
this.anchorNumber(anchor, "h-offset"),
|
|
1409
|
+
pageNumber
|
|
1410
|
+
);
|
|
1411
|
+
const top = this.resolveAnchorAxis(
|
|
1412
|
+
vertical,
|
|
1413
|
+
height,
|
|
1414
|
+
anchor.getAttribute("data-docx-anchor-v-align"),
|
|
1415
|
+
this.anchorNumber(anchor, "v-offset"),
|
|
1416
|
+
pageNumber
|
|
1417
|
+
);
|
|
1418
|
+
pageBox.appendChild(anchor);
|
|
1419
|
+
anchor.style.position = "absolute";
|
|
1420
|
+
anchor.style.left = `${left}pt`;
|
|
1421
|
+
anchor.style.top = `${top}pt`;
|
|
1422
|
+
anchor.style.margin = "0";
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
anchorNumber(anchor, suffix) {
|
|
1426
|
+
const raw = anchor.getAttribute(`data-docx-anchor-${suffix}`);
|
|
1427
|
+
if (raw === null) return void 0;
|
|
1428
|
+
const value = Number(raw);
|
|
1429
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1430
|
+
}
|
|
1431
|
+
horizontalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
1432
|
+
const leftMargin = { start: 0, size: dims.marginLeft };
|
|
1433
|
+
const rightMargin = {
|
|
1434
|
+
start: dims.marginLeft + dims.contentWidth,
|
|
1435
|
+
size: dims.marginRight
|
|
1436
|
+
};
|
|
1437
|
+
switch (relativeFrom) {
|
|
1438
|
+
case "page":
|
|
1439
|
+
return { start: 0, size: dims.pageWidth };
|
|
1440
|
+
case "character":
|
|
1441
|
+
return { start: context.staticLeft, size: 0 };
|
|
1442
|
+
case "leftMargin":
|
|
1443
|
+
return leftMargin;
|
|
1444
|
+
case "rightMargin":
|
|
1445
|
+
return rightMargin;
|
|
1446
|
+
case "insideMargin":
|
|
1447
|
+
return pageNumber % 2 === 1 ? leftMargin : rightMargin;
|
|
1448
|
+
case "outsideMargin":
|
|
1449
|
+
return pageNumber % 2 === 1 ? rightMargin : leftMargin;
|
|
1450
|
+
case "paragraph":
|
|
1451
|
+
return { start: context.paragraphLeft, size: context.paragraphWidth };
|
|
1452
|
+
case "column":
|
|
1453
|
+
case "margin":
|
|
1454
|
+
default:
|
|
1455
|
+
return { start: dims.marginLeft, size: dims.contentWidth };
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
verticalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
1459
|
+
const topMargin = { start: 0, size: dims.marginTop };
|
|
1460
|
+
const bottomMargin = {
|
|
1461
|
+
start: dims.marginTop + dims.contentHeight,
|
|
1462
|
+
size: dims.marginBottom
|
|
1463
|
+
};
|
|
1464
|
+
switch (relativeFrom) {
|
|
1465
|
+
case "page":
|
|
1466
|
+
return { start: 0, size: dims.pageHeight };
|
|
1467
|
+
case "paragraph":
|
|
1468
|
+
return { start: context.paragraphTop, size: context.paragraphHeight };
|
|
1469
|
+
case "line":
|
|
1470
|
+
return { start: context.staticTop, size: context.lineHeight };
|
|
1471
|
+
case "topMargin":
|
|
1472
|
+
return topMargin;
|
|
1473
|
+
case "bottomMargin":
|
|
1474
|
+
return bottomMargin;
|
|
1475
|
+
case "insideMargin":
|
|
1476
|
+
return pageNumber % 2 === 1 ? topMargin : bottomMargin;
|
|
1477
|
+
case "outsideMargin":
|
|
1478
|
+
return pageNumber % 2 === 1 ? bottomMargin : topMargin;
|
|
1479
|
+
case "margin":
|
|
1480
|
+
default:
|
|
1481
|
+
return { start: dims.marginTop, size: dims.contentHeight };
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
resolveAnchorAxis(reference, objectSize, alignment, offset, pageNumber) {
|
|
1485
|
+
if (offset !== void 0) return reference.start + offset;
|
|
1486
|
+
let fraction = 0;
|
|
1487
|
+
if (alignment === "center") fraction = 0.5;
|
|
1488
|
+
else if (alignment === "right" || alignment === "bottom") fraction = 1;
|
|
1489
|
+
else if (alignment === "inside") fraction = pageNumber % 2 === 1 ? 0 : 1;
|
|
1490
|
+
else if (alignment === "outside") fraction = pageNumber % 2 === 1 ? 1 : 0;
|
|
1491
|
+
return reference.start + (reference.size - objectSize) * fraction;
|
|
1492
|
+
}
|
|
1309
1493
|
/**
|
|
1310
1494
|
* Creates a page container element.
|
|
1311
1495
|
*/
|
|
@@ -1332,22 +1516,22 @@ var DocxodusPagination = (() => {
|
|
|
1332
1516
|
pageBox.dataset.pageNumber = String(pageNumber);
|
|
1333
1517
|
pageBox.dataset.sectionIndex = String(sectionIndex);
|
|
1334
1518
|
pageBox.dataset.pageInSection = String(pageInSection);
|
|
1335
|
-
const
|
|
1519
|
+
const bands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
1336
1520
|
const headerSource = this.selectHeader(sectionIndex, pageInSection, pageNumber);
|
|
1337
1521
|
if (headerSource) {
|
|
1338
1522
|
const headerDiv = document.createElement("div");
|
|
1339
1523
|
headerDiv.className = `${this.cssPrefix}header`;
|
|
1340
1524
|
headerDiv.style.position = "absolute";
|
|
1341
|
-
headerDiv.style.top =
|
|
1525
|
+
headerDiv.style.top = `${bands.headerTop}pt`;
|
|
1526
|
+
headerDiv.style.bottom = "auto";
|
|
1342
1527
|
headerDiv.style.left = `${dims.marginLeft}pt`;
|
|
1343
1528
|
headerDiv.style.width = `${dims.contentWidth}pt`;
|
|
1344
|
-
headerDiv.style.height = `${
|
|
1529
|
+
headerDiv.style.height = `${bands.headerHeight}pt`;
|
|
1345
1530
|
headerDiv.style.overflow = "hidden";
|
|
1346
1531
|
headerDiv.style.boxSizing = "border-box";
|
|
1347
1532
|
headerDiv.style.display = "flex";
|
|
1348
1533
|
headerDiv.style.flexDirection = "column";
|
|
1349
|
-
headerDiv.style.justifyContent = "flex-
|
|
1350
|
-
headerDiv.style.paddingBottom = "4pt";
|
|
1534
|
+
headerDiv.style.justifyContent = "flex-start";
|
|
1351
1535
|
for (const child of Array.from(headerSource.childNodes)) {
|
|
1352
1536
|
const clonedheaderDiv = child.cloneNode(true);
|
|
1353
1537
|
if (clonedheaderDiv.nodeType === 1) this.makeClonedStoryInert(clonedheaderDiv);
|
|
@@ -1355,8 +1539,8 @@ var DocxodusPagination = (() => {
|
|
|
1355
1539
|
}
|
|
1356
1540
|
pageBox.appendChild(headerDiv);
|
|
1357
1541
|
}
|
|
1358
|
-
const contentAreaTop =
|
|
1359
|
-
const contentAreaHeight =
|
|
1542
|
+
const contentAreaTop = bands.bodyTop;
|
|
1543
|
+
const contentAreaHeight = bands.bodyHeight;
|
|
1360
1544
|
const contentArea = document.createElement("div");
|
|
1361
1545
|
contentArea.className = `${this.cssPrefix}content`;
|
|
1362
1546
|
contentArea.style.position = "absolute";
|
|
@@ -1371,23 +1555,23 @@ var DocxodusPagination = (() => {
|
|
|
1371
1555
|
pageBox.appendChild(contentArea);
|
|
1372
1556
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
1373
1557
|
if (footnoteIds.length > 0 || hasContinuation) {
|
|
1374
|
-
this.addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes);
|
|
1558
|
+
this.addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes);
|
|
1375
1559
|
}
|
|
1376
1560
|
const footerSource = this.selectFooter(sectionIndex, pageInSection, pageNumber);
|
|
1377
1561
|
if (footerSource) {
|
|
1378
1562
|
const footerDiv = document.createElement("div");
|
|
1379
1563
|
footerDiv.className = `${this.cssPrefix}footer`;
|
|
1380
1564
|
footerDiv.style.position = "absolute";
|
|
1381
|
-
footerDiv.style.
|
|
1565
|
+
footerDiv.style.top = "auto";
|
|
1566
|
+
footerDiv.style.bottom = `${dims.footerDistance}pt`;
|
|
1382
1567
|
footerDiv.style.left = `${dims.marginLeft}pt`;
|
|
1383
1568
|
footerDiv.style.width = `${dims.contentWidth}pt`;
|
|
1384
|
-
footerDiv.style.height = `${
|
|
1569
|
+
footerDiv.style.height = `${bands.footerHeight}pt`;
|
|
1385
1570
|
footerDiv.style.overflow = "hidden";
|
|
1386
1571
|
footerDiv.style.boxSizing = "border-box";
|
|
1387
1572
|
footerDiv.style.display = "flex";
|
|
1388
1573
|
footerDiv.style.flexDirection = "column";
|
|
1389
|
-
footerDiv.style.justifyContent = "flex-
|
|
1390
|
-
footerDiv.style.paddingTop = "4pt";
|
|
1574
|
+
footerDiv.style.justifyContent = "flex-end";
|
|
1391
1575
|
for (const child of Array.from(footerSource.childNodes)) {
|
|
1392
1576
|
const clonedfooterDiv = child.cloneNode(true);
|
|
1393
1577
|
if (clonedfooterDiv.nodeType === 1) this.makeClonedStoryInert(clonedfooterDiv);
|
|
@@ -1402,6 +1586,7 @@ var DocxodusPagination = (() => {
|
|
|
1402
1586
|
pageBox.appendChild(pageNum);
|
|
1403
1587
|
}
|
|
1404
1588
|
this.containerElement.appendChild(pageBox);
|
|
1589
|
+
this.positionDrawingAnchors(pageBox, contentArea, dims, pageNumber);
|
|
1405
1590
|
const notesEl = pageBox.querySelector(`.${this.cssPrefix}footnotes`);
|
|
1406
1591
|
if (notesEl) {
|
|
1407
1592
|
const notesHeightPt = pxToPt(notesEl.getBoundingClientRect().height);
|
package/dist/pagination.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and flows it across fixed-size page containers based on document dimensions.
|
|
6
6
|
*/
|
|
7
7
|
import type { PageDimensions } from "./page-geometry.js";
|
|
8
|
-
export type { PageDimensions } from "./page-geometry.js";
|
|
8
|
+
export type { PageBands, PageDimensions } from "./page-geometry.js";
|
|
9
9
|
/**
|
|
10
10
|
* Headers and footers for a specific section.
|
|
11
11
|
*/
|
|
@@ -283,16 +283,28 @@ export declare class PaginationEngine {
|
|
|
283
283
|
*/
|
|
284
284
|
private selectFooter;
|
|
285
285
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
286
|
+
* The header, body, and footer bands for one page position.
|
|
287
|
+
*
|
|
288
|
+
* The single owner of "where does anything sit vertically on this page" — placement in
|
|
289
|
+
* {@link createPage}, the body budget the flow loop spends, and the note area's anchor all
|
|
290
|
+
* read it, so those three cannot disagree about where the body ends.
|
|
291
|
+
*
|
|
292
|
+
* Deterministic: it depends only on the section's page setup and the registry's pre-measured
|
|
293
|
+
* story heights, never on the page's content, which is what keeps it lazy-loading compatible.
|
|
294
|
+
*/
|
|
295
|
+
private getPageBands;
|
|
296
|
+
/**
|
|
297
|
+
* The measured height of the running story this page position selects, mirroring
|
|
298
|
+
* {@link selectHeader}/{@link selectFooter}. Zero when the page has no such story.
|
|
291
299
|
*/
|
|
292
|
-
private
|
|
300
|
+
private selectStoryHeight;
|
|
293
301
|
/**
|
|
294
302
|
* Measures the content height of a header or footer element.
|
|
295
|
-
*
|
|
303
|
+
*
|
|
304
|
+
* This is what tells {@link resolvePageBands} whether the story stays inside its margin or
|
|
305
|
+
* pushes the body, so it must measure the story ALONE — any padding added here would have to
|
|
306
|
+
* be added to the rendered band too, and the two drifting apart is exactly how a header
|
|
307
|
+
* silently starts overlapping body text.
|
|
296
308
|
*/
|
|
297
309
|
private measureHeaderFooterHeight;
|
|
298
310
|
/**
|
|
@@ -315,6 +327,19 @@ export declare class PaginationEngine {
|
|
|
315
327
|
* cloned node cannot be uniquely addressed.
|
|
316
328
|
*/
|
|
317
329
|
private makeClonedStoryInert;
|
|
330
|
+
/**
|
|
331
|
+
* Resolves floating DrawingML objects after their anchor paragraphs have landed on a page.
|
|
332
|
+
*
|
|
333
|
+
* The converter deliberately carries the OOXML bases and offsets as data instead of flattening
|
|
334
|
+
* them into CSS: page/margin/column bases belong to the page, while paragraph/line/character
|
|
335
|
+
* bases belong to the laid-out anchor. Once both coordinate systems exist, promote the object
|
|
336
|
+
* from the clipped text column into the page box and position it in one shared point space.
|
|
337
|
+
*/
|
|
338
|
+
private positionDrawingAnchors;
|
|
339
|
+
private anchorNumber;
|
|
340
|
+
private horizontalAnchorReference;
|
|
341
|
+
private verticalAnchorReference;
|
|
342
|
+
private resolveAnchorAxis;
|
|
318
343
|
/**
|
|
319
344
|
* Creates a page container element.
|
|
320
345
|
*/
|