docxodus 9.7.0 → 9.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/LICENSE +22 -0
- package/README.md +0 -1
- package/dist/editor.bundle.js +454 -99
- 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 +454 -99
- package/dist/embed.iife.js +454 -99
- 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 +416 -91
- package/dist/pagination.d.ts +61 -8
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +353 -105
- package/dist/pagination.js.map +1 -1
- package/dist/ribbon-chrome.d.ts +1 -1
- package/dist/ribbon-chrome.d.ts.map +1 -1
- package/dist/ribbon-chrome.js +1 -0
- package/dist/ribbon-chrome.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.Collections.Concurrent.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.Concurrent.wasm.br +0 -0
- package/dist/wasm/_framework/System.Collections.Immutable.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.Immutable.wasm.br +0 -0
- package/dist/wasm/_framework/System.Collections.NonGeneric.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.NonGeneric.wasm.br +0 -0
- package/dist/wasm/_framework/System.Collections.Specialized.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.Specialized.wasm.br +0 -0
- package/dist/wasm/_framework/System.Collections.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.wasm.br +0 -0
- package/dist/wasm/_framework/System.ComponentModel.Primitives.wasm +0 -0
- package/dist/wasm/_framework/System.ComponentModel.Primitives.wasm.br +0 -0
- package/dist/wasm/_framework/System.ComponentModel.TypeConverter.wasm +0 -0
- package/dist/wasm/_framework/System.ComponentModel.TypeConverter.wasm.br +0 -0
- package/dist/wasm/_framework/System.ComponentModel.wasm +0 -0
- package/dist/wasm/_framework/System.ComponentModel.wasm.br +0 -0
- package/dist/wasm/_framework/System.Console.wasm +0 -0
- package/dist/wasm/_framework/System.Console.wasm.br +0 -0
- package/dist/wasm/_framework/System.Diagnostics.Process.wasm +0 -0
- package/dist/wasm/_framework/System.Diagnostics.Process.wasm.br +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm.br +0 -0
- package/dist/wasm/_framework/System.IO.Pipelines.wasm +0 -0
- package/dist/wasm/_framework/System.IO.Pipelines.wasm.br +0 -0
- package/dist/wasm/_framework/System.Linq.Expressions.wasm +0 -0
- package/dist/wasm/_framework/System.Linq.Expressions.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.Memory.wasm +0 -0
- package/dist/wasm/_framework/System.Memory.wasm.br +0 -0
- package/dist/wasm/_framework/System.Net.Http.wasm +0 -0
- package/dist/wasm/_framework/System.Net.Http.wasm.br +0 -0
- package/dist/wasm/_framework/System.Net.Primitives.wasm +0 -0
- package/dist/wasm/_framework/System.Net.Primitives.wasm.br +0 -0
- package/dist/wasm/_framework/System.ObjectModel.wasm +0 -0
- package/dist/wasm/_framework/System.ObjectModel.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/System.Private.Uri.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Uri.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Xml.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Xml.wasm.br +0 -0
- package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
- package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm.br +0 -0
- package/dist/wasm/_framework/System.Runtime.wasm +0 -0
- package/dist/wasm/_framework/System.Runtime.wasm.br +0 -0
- package/dist/wasm/_framework/System.Security.Cryptography.wasm +0 -0
- package/dist/wasm/_framework/System.Security.Cryptography.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.Encodings.Web.wasm +0 -0
- package/dist/wasm/_framework/System.Text.Encodings.Web.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.Json.wasm +0 -0
- package/dist/wasm/_framework/System.Text.Json.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.RegularExpressions.wasm +0 -0
- package/dist/wasm/_framework/System.Text.RegularExpressions.wasm.br +0 -0
- package/dist/wasm/_framework/System.Xml.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Xml.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Xml.XDocument.wasm +0 -0
- package/dist/wasm/_framework/System.Xml.XDocument.wasm.br +0 -0
- package/dist/wasm/_framework/System.wasm +0 -0
- package/dist/wasm/_framework/System.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.boot.js +35 -35
- package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
- package/dist/wasm/_framework/dotnet.js +1 -1
- package/dist/wasm/_framework/dotnet.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.js +3 -3
- package/dist/wasm/_framework/dotnet.native.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.runtime.js +1 -1
- package/dist/wasm/_framework/dotnet.runtime.js.br +0 -0
- package/package.json +14 -5
- package/dist/wasm/index.html +0 -238
- package/dist/wasm/main.js +0 -26
|
@@ -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,12 +90,44 @@ 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
|
|
|
98
127
|
// src/pagination.ts
|
|
128
|
+
function samePageBox(a, b) {
|
|
129
|
+
return a.pageWidth === b.pageWidth && a.pageHeight === b.pageHeight && a.marginTop === b.marginTop && a.marginRight === b.marginRight && a.marginBottom === b.marginBottom && a.marginLeft === b.marginLeft;
|
|
130
|
+
}
|
|
99
131
|
var MAX_FOOTNOTE_AREA_RATIO = 0.6;
|
|
100
132
|
var MIN_BODY_CONTENT_HEIGHT = 72;
|
|
101
133
|
var PaginationEngine = class {
|
|
@@ -141,16 +173,43 @@ var DocxodusPagination = (() => {
|
|
|
141
173
|
);
|
|
142
174
|
this.pageNumbering = this.parsePageNumbering(sections);
|
|
143
175
|
const sectionsToProcess = sections.length > 0 ? Array.from(sections) : [this.stagingElement];
|
|
176
|
+
const runs = [];
|
|
144
177
|
for (const section of sectionsToProcess) {
|
|
145
|
-
const sectionIndex = parseInt(section.dataset.sectionIndex || "0", 10);
|
|
146
178
|
const dims = parseSectionDimensions(section);
|
|
179
|
+
const previous = runs[runs.length - 1];
|
|
180
|
+
if (previous && section.dataset.sectionType === "continuous" && samePageBox(previous.dims, dims)) {
|
|
181
|
+
previous.sections.push(section);
|
|
182
|
+
} else {
|
|
183
|
+
runs.push({
|
|
184
|
+
sections: [section],
|
|
185
|
+
sectionIndex: parseInt(section.dataset.sectionIndex || "0", 10),
|
|
186
|
+
dims
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
for (const run of runs) {
|
|
147
191
|
this.stagingElement.style.visibility = "hidden";
|
|
148
192
|
this.stagingElement.style.position = "absolute";
|
|
149
193
|
this.stagingElement.style.left = "-9999px";
|
|
150
194
|
this.stagingElement.style.display = "block";
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
195
|
+
const blocks = [];
|
|
196
|
+
for (const section of run.sections) {
|
|
197
|
+
section.style.width = `${run.dims.contentWidth}pt`;
|
|
198
|
+
const columnCount = parseInt(section.dataset.cols || "1", 10);
|
|
199
|
+
if (columnCount > 1) {
|
|
200
|
+
const gap = parseFloat(section.dataset.colGap || "");
|
|
201
|
+
blocks.push(...this.buildColumnBlocks(
|
|
202
|
+
section,
|
|
203
|
+
run.dims,
|
|
204
|
+
run.sectionIndex,
|
|
205
|
+
columnCount,
|
|
206
|
+
Number.isFinite(gap) ? gap : 36
|
|
207
|
+
));
|
|
208
|
+
} else {
|
|
209
|
+
blocks.push(...this.measureBlocks(section, run.dims));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const sectionPages = this.flowToPages(blocks, run.dims, pageNumber, run.sectionIndex);
|
|
154
213
|
pages.push(...sectionPages);
|
|
155
214
|
pageNumber += sectionPages.length;
|
|
156
215
|
}
|
|
@@ -239,8 +298,67 @@ var DocxodusPagination = (() => {
|
|
|
239
298
|
keepWithNext: child.dataset.keepWithNext === "true",
|
|
240
299
|
keepLines: child.dataset.keepLines === "true",
|
|
241
300
|
pageBreakBefore: child.dataset.pageBreakBefore === "true",
|
|
242
|
-
isPageBreak
|
|
301
|
+
isPageBreak,
|
|
302
|
+
isWordParagraph: this.isWordParagraphElement(child)
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return blocks;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Flows a multi-column (`w:cols`) section's children into CSS-multicol container
|
|
309
|
+
* blocks. Word lays such a section out as N columns inside the same body extent;
|
|
310
|
+
* a balanced `column-count` container reproduces that geometry, and the paginator
|
|
311
|
+
* then places each container as one ordinary measured block. A container grows
|
|
312
|
+
* greedily until its balanced height would exceed the smallest page body available
|
|
313
|
+
* to the section, so a long columned section still splits across pages at block
|
|
314
|
+
* boundaries. Each child lands in exactly one container, so anchors never
|
|
315
|
+
* duplicate. An explicit page break child passes through as its own block, which
|
|
316
|
+
* ends the current container and lets the normal flow logic turn the page.
|
|
317
|
+
*/
|
|
318
|
+
buildColumnBlocks(section, dims, sectionIndex, columnCount, columnGapPt) {
|
|
319
|
+
const children = Array.from(section.children);
|
|
320
|
+
const blocks = [];
|
|
321
|
+
const maxFragmentHeight = this.smallestEffectiveContentHeight(dims, sectionIndex);
|
|
322
|
+
const isBreak = (child) => child.dataset.pageBreak === "true" || child.classList.contains(`${this.cssPrefix}break`);
|
|
323
|
+
const makeContainer = (slice) => {
|
|
324
|
+
const container = document.createElement("div");
|
|
325
|
+
container.style.columnCount = String(columnCount);
|
|
326
|
+
container.style.columnGap = `${columnGapPt}pt`;
|
|
327
|
+
for (const child of slice) {
|
|
328
|
+
container.appendChild(child.cloneNode(true));
|
|
329
|
+
}
|
|
330
|
+
return container;
|
|
331
|
+
};
|
|
332
|
+
let start = 0;
|
|
333
|
+
while (start < children.length) {
|
|
334
|
+
if (isBreak(children[start])) {
|
|
335
|
+
blocks.push(this.measureElement(children[start], dims));
|
|
336
|
+
start++;
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
let end = start + 1;
|
|
340
|
+
let container = makeContainer(children.slice(start, end));
|
|
341
|
+
let measured = this.measureElement(container, dims);
|
|
342
|
+
while (end < children.length && !isBreak(children[end])) {
|
|
343
|
+
const candidate = makeContainer(children.slice(start, end + 1));
|
|
344
|
+
const candidateMeasured = this.measureElement(candidate, dims);
|
|
345
|
+
if (candidateMeasured.heightPt > maxFragmentHeight) break;
|
|
346
|
+
container = candidate;
|
|
347
|
+
measured = candidateMeasured;
|
|
348
|
+
end++;
|
|
349
|
+
}
|
|
350
|
+
blocks.push({
|
|
351
|
+
element: container,
|
|
352
|
+
heightPt: measured.heightPt,
|
|
353
|
+
marginTopPt: measured.marginTopPt,
|
|
354
|
+
marginBottomPt: measured.marginBottomPt,
|
|
355
|
+
keepWithNext: false,
|
|
356
|
+
keepLines: false,
|
|
357
|
+
pageBreakBefore: false,
|
|
358
|
+
isPageBreak: false,
|
|
359
|
+
isWordParagraph: false
|
|
243
360
|
});
|
|
361
|
+
start = end;
|
|
244
362
|
}
|
|
245
363
|
return blocks;
|
|
246
364
|
}
|
|
@@ -268,7 +386,8 @@ var DocxodusPagination = (() => {
|
|
|
268
386
|
keepWithNext: element.dataset.keepWithNext === "true",
|
|
269
387
|
keepLines: element.dataset.keepLines === "true",
|
|
270
388
|
pageBreakBefore: element.dataset.pageBreakBefore === "true",
|
|
271
|
-
isPageBreak: element.dataset.pageBreak === "true" || element.classList.contains(`${this.cssPrefix}break`)
|
|
389
|
+
isPageBreak: element.dataset.pageBreak === "true" || element.classList.contains(`${this.cssPrefix}break`),
|
|
390
|
+
isWordParagraph: this.isWordParagraphElement(element)
|
|
272
391
|
};
|
|
273
392
|
this.stagingElement.removeChild(measurementHost);
|
|
274
393
|
return measured;
|
|
@@ -300,10 +419,15 @@ var DocxodusPagination = (() => {
|
|
|
300
419
|
* collapsed-margin rules as normal block placement. The trailing margin is
|
|
301
420
|
* intentionally excluded, matching the individual block fit check.
|
|
302
421
|
*/
|
|
303
|
-
measureKeepWithNextChainBodyHeight(chain, previousMarginBottomPt, isFirstOnPage) {
|
|
422
|
+
measureKeepWithNextChainBodyHeight(chain, previousMarginBottomPt, isFirstOnPage, pageInSection) {
|
|
304
423
|
const firstBlock = chain[0];
|
|
305
424
|
if (!firstBlock) return 0;
|
|
306
|
-
const firstMarginTop =
|
|
425
|
+
const firstMarginTop = this.effectiveBlockMarginTop(
|
|
426
|
+
firstBlock,
|
|
427
|
+
previousMarginBottomPt,
|
|
428
|
+
isFirstOnPage,
|
|
429
|
+
pageInSection
|
|
430
|
+
);
|
|
307
431
|
let bodyHeight = firstMarginTop + firstBlock.heightPt;
|
|
308
432
|
for (let index = 1; index < chain.length; index++) {
|
|
309
433
|
const previousBlock = chain[index - 1];
|
|
@@ -312,6 +436,35 @@ var DocxodusPagination = (() => {
|
|
|
312
436
|
}
|
|
313
437
|
return bodyHeight;
|
|
314
438
|
}
|
|
439
|
+
/** Word paragraphs render as `p`, or as `h1`–`h6` when their style has an outline level. */
|
|
440
|
+
isWordParagraphElement(element) {
|
|
441
|
+
return element.tagName === "P" || /^H[1-6]$/.test(element.tagName);
|
|
442
|
+
}
|
|
443
|
+
shouldSuppressPageTopSpacing(block, isFirstOnPage, pageInSection) {
|
|
444
|
+
return isFirstOnPage && pageInSection > 1 && block.isWordParagraph === true;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Resolves the part of a block's top margin that consumes the current page.
|
|
448
|
+
*
|
|
449
|
+
* In Word's native DOCX layout, paragraph space-before is suppressed when a paragraph is the
|
|
450
|
+
* first body block on a later page of the SAME section. The first page of a document/section is
|
|
451
|
+
* the exception and keeps its spacing. Tables and other block margins are not paragraph spacing,
|
|
452
|
+
* so they continue to use the ordinary CSS collapsing rule.
|
|
453
|
+
*/
|
|
454
|
+
effectiveBlockMarginTop(block, previousMarginBottomPt, isFirstOnPage, pageInSection) {
|
|
455
|
+
if (this.shouldSuppressPageTopSpacing(block, isFirstOnPage, pageInSection)) {
|
|
456
|
+
return 0;
|
|
457
|
+
}
|
|
458
|
+
return isFirstOnPage ? block.marginTopPt : Math.max(block.marginTopPt, previousMarginBottomPt) - previousMarginBottomPt;
|
|
459
|
+
}
|
|
460
|
+
/** Clone a source block with the same page-top spacing decision used by the height budget. */
|
|
461
|
+
cloneBlockForPage(block, isFirstOnPage, pageInSection) {
|
|
462
|
+
const clone = block.element.cloneNode(true);
|
|
463
|
+
if (this.shouldSuppressPageTopSpacing(block, isFirstOnPage, pageInSection)) {
|
|
464
|
+
clone.style.setProperty("margin-top", "0", "important");
|
|
465
|
+
}
|
|
466
|
+
return clone;
|
|
467
|
+
}
|
|
315
468
|
/**
|
|
316
469
|
* Finds footnote references introduced by a sequence of blocks, preserving
|
|
317
470
|
* document order and excluding references already assigned to the page.
|
|
@@ -336,9 +489,9 @@ var DocxodusPagination = (() => {
|
|
|
336
489
|
*/
|
|
337
490
|
smallestEffectiveContentHeight(dims, sectionIndex) {
|
|
338
491
|
return Math.min(
|
|
339
|
-
this.
|
|
340
|
-
this.
|
|
341
|
-
this.
|
|
492
|
+
this.getPageBands(dims, sectionIndex, 1, 1).bodyHeight,
|
|
493
|
+
this.getPageBands(dims, sectionIndex, 2, 1).bodyHeight,
|
|
494
|
+
this.getPageBands(dims, sectionIndex, 2, 2).bodyHeight
|
|
342
495
|
);
|
|
343
496
|
}
|
|
344
497
|
/**
|
|
@@ -862,7 +1015,7 @@ var DocxodusPagination = (() => {
|
|
|
862
1015
|
/**
|
|
863
1016
|
* Adds footnotes to a page container, including continuation content.
|
|
864
1017
|
*/
|
|
865
|
-
addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes) {
|
|
1018
|
+
addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes) {
|
|
866
1019
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
867
1020
|
if (footnoteIds.length === 0 && !hasContinuation) {
|
|
868
1021
|
return;
|
|
@@ -873,12 +1026,12 @@ var DocxodusPagination = (() => {
|
|
|
873
1026
|
const partialFootnoteIds = new Set(partialFootnotes?.map((p) => p.footnoteId) || []);
|
|
874
1027
|
const maxFootnoteHeight = Math.min(
|
|
875
1028
|
footnoteHeight,
|
|
876
|
-
|
|
1029
|
+
bands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO
|
|
877
1030
|
);
|
|
878
1031
|
const footnotesDiv = document.createElement("div");
|
|
879
1032
|
footnotesDiv.className = `${this.cssPrefix}footnotes`;
|
|
880
1033
|
footnotesDiv.style.position = "absolute";
|
|
881
|
-
footnotesDiv.style.bottom = `${dims.
|
|
1034
|
+
footnotesDiv.style.bottom = `${dims.pageHeight - (bands.bodyTop + bands.bodyHeight)}pt`;
|
|
882
1035
|
footnotesDiv.style.left = `${dims.marginLeft}pt`;
|
|
883
1036
|
footnotesDiv.style.width = `${dims.contentWidth}pt`;
|
|
884
1037
|
footnotesDiv.style.boxSizing = "border-box";
|
|
@@ -952,50 +1105,51 @@ var DocxodusPagination = (() => {
|
|
|
952
1105
|
return sectionHf.footerDefault;
|
|
953
1106
|
}
|
|
954
1107
|
/**
|
|
955
|
-
*
|
|
956
|
-
*
|
|
957
|
-
*
|
|
958
|
-
*
|
|
959
|
-
*
|
|
1108
|
+
* The header, body, and footer bands for one page position.
|
|
1109
|
+
*
|
|
1110
|
+
* The single owner of "where does anything sit vertically on this page" — placement in
|
|
1111
|
+
* {@link createPage}, the body budget the flow loop spends, and the note area's anchor all
|
|
1112
|
+
* read it, so those three cannot disagree about where the body ends.
|
|
1113
|
+
*
|
|
1114
|
+
* Deterministic: it depends only on the section's page setup and the registry's pre-measured
|
|
1115
|
+
* story heights, never on the page's content, which is what keeps it lazy-loading compatible.
|
|
960
1116
|
*/
|
|
961
|
-
|
|
1117
|
+
getPageBands(dims, sectionIndex, pageInSection, globalPageNumber) {
|
|
962
1118
|
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 };
|
|
1119
|
+
return resolvePageBands(
|
|
1120
|
+
dims,
|
|
1121
|
+
this.selectStoryHeight(
|
|
1122
|
+
sectionHf?.headerFirstHeight,
|
|
1123
|
+
sectionHf?.headerEvenHeight,
|
|
1124
|
+
sectionHf?.headerDefaultHeight,
|
|
1125
|
+
pageInSection,
|
|
1126
|
+
globalPageNumber
|
|
1127
|
+
),
|
|
1128
|
+
this.selectStoryHeight(
|
|
1129
|
+
sectionHf?.footerFirstHeight,
|
|
1130
|
+
sectionHf?.footerEvenHeight,
|
|
1131
|
+
sectionHf?.footerDefaultHeight,
|
|
1132
|
+
pageInSection,
|
|
1133
|
+
globalPageNumber
|
|
1134
|
+
)
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* The measured height of the running story this page position selects, mirroring
|
|
1139
|
+
* {@link selectHeader}/{@link selectFooter}. Zero when the page has no such story.
|
|
1140
|
+
*/
|
|
1141
|
+
selectStoryHeight(first, even, fallback, pageInSection, globalPageNumber) {
|
|
1142
|
+
if (pageInSection === 1 && first != null) return first;
|
|
1143
|
+
if (globalPageNumber % 2 === 0 && even != null) return even;
|
|
1144
|
+
return fallback ?? 0;
|
|
995
1145
|
}
|
|
996
1146
|
/**
|
|
997
1147
|
* Measures the content height of a header or footer element.
|
|
998
|
-
*
|
|
1148
|
+
*
|
|
1149
|
+
* This is what tells {@link resolvePageBands} whether the story stays inside its margin or
|
|
1150
|
+
* pushes the body, so it must measure the story ALONE — any padding added here would have to
|
|
1151
|
+
* be added to the rendered band too, and the two drifting apart is exactly how a header
|
|
1152
|
+
* silently starts overlapping body text.
|
|
999
1153
|
*/
|
|
1000
1154
|
measureHeaderFooterHeight(source, contentWidth) {
|
|
1001
1155
|
const measureContainer = document.createElement("div");
|
|
@@ -1003,7 +1157,6 @@ var DocxodusPagination = (() => {
|
|
|
1003
1157
|
measureContainer.style.visibility = "hidden";
|
|
1004
1158
|
measureContainer.style.width = `${contentWidth}pt`;
|
|
1005
1159
|
measureContainer.style.left = "-9999px";
|
|
1006
|
-
measureContainer.style.paddingBottom = "4pt";
|
|
1007
1160
|
for (const child of Array.from(source.childNodes)) {
|
|
1008
1161
|
measureContainer.appendChild(child.cloneNode(true));
|
|
1009
1162
|
}
|
|
@@ -1023,7 +1176,7 @@ var DocxodusPagination = (() => {
|
|
|
1023
1176
|
let currentContent = [];
|
|
1024
1177
|
let pageNumber = startPageNumber;
|
|
1025
1178
|
let pageInSection = 1;
|
|
1026
|
-
let {
|
|
1179
|
+
let { bodyHeight: effectiveContentHeight } = this.getPageBands(
|
|
1027
1180
|
dims,
|
|
1028
1181
|
sectionIndex,
|
|
1029
1182
|
pageInSection,
|
|
@@ -1058,8 +1211,8 @@ var DocxodusPagination = (() => {
|
|
|
1058
1211
|
pageNumber++;
|
|
1059
1212
|
pageInSection++;
|
|
1060
1213
|
currentContent = [];
|
|
1061
|
-
const
|
|
1062
|
-
effectiveContentHeight =
|
|
1214
|
+
const newBands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
1215
|
+
effectiveContentHeight = newBands.bodyHeight;
|
|
1063
1216
|
remainingHeight = effectiveContentHeight;
|
|
1064
1217
|
prevMarginBottomPt = 0;
|
|
1065
1218
|
currentFootnoteIds = [];
|
|
@@ -1117,11 +1270,12 @@ var DocxodusPagination = (() => {
|
|
|
1117
1270
|
const currentChainHeight = this.measureKeepWithNextChainBodyHeight(
|
|
1118
1271
|
keepChain,
|
|
1119
1272
|
prevMarginBottomPt,
|
|
1120
|
-
currentContent.length === 0
|
|
1273
|
+
currentContent.length === 0,
|
|
1274
|
+
pageInSection
|
|
1121
1275
|
) + additionalChainFootnoteHeight;
|
|
1122
1276
|
const currentAvailableHeight = remainingHeight - currentFootnoteHeight;
|
|
1123
1277
|
if (currentChainHeight > currentAvailableHeight) {
|
|
1124
|
-
const
|
|
1278
|
+
const nextPageBands = this.getPageBands(
|
|
1125
1279
|
dims,
|
|
1126
1280
|
sectionIndex,
|
|
1127
1281
|
pageInSection + 1,
|
|
@@ -1130,14 +1284,15 @@ var DocxodusPagination = (() => {
|
|
|
1130
1284
|
const freshChainBodyHeight = this.measureKeepWithNextChainBodyHeight(
|
|
1131
1285
|
keepChain,
|
|
1132
1286
|
0,
|
|
1133
|
-
true
|
|
1287
|
+
true,
|
|
1288
|
+
pageInSection + 1
|
|
1134
1289
|
);
|
|
1135
1290
|
const freshChainFootnoteHeight = this.measureFootnotesHeight(
|
|
1136
1291
|
newChainFootnoteIds,
|
|
1137
1292
|
dims.contentWidth,
|
|
1138
1293
|
nextPageContinuation
|
|
1139
1294
|
);
|
|
1140
|
-
if (freshChainBodyHeight + freshChainFootnoteHeight <=
|
|
1295
|
+
if (freshChainBodyHeight + freshChainFootnoteHeight <= nextPageBands.bodyHeight) {
|
|
1141
1296
|
finishPage();
|
|
1142
1297
|
}
|
|
1143
1298
|
}
|
|
@@ -1156,10 +1311,12 @@ var DocxodusPagination = (() => {
|
|
|
1156
1311
|
additionalFootnoteHeight = totalFootnoteHeight - currentFootnoteHeight;
|
|
1157
1312
|
}
|
|
1158
1313
|
const isFirstOnPage = currentContent.length === 0;
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1314
|
+
const effectiveMarginTop = this.effectiveBlockMarginTop(
|
|
1315
|
+
block,
|
|
1316
|
+
prevMarginBottomPt,
|
|
1317
|
+
isFirstOnPage,
|
|
1318
|
+
pageInSection
|
|
1319
|
+
);
|
|
1163
1320
|
const blockSpace = effectiveMarginTop + block.heightPt + additionalFootnoteHeight;
|
|
1164
1321
|
const effectiveRemainingHeight = remainingHeight - currentFootnoteHeight;
|
|
1165
1322
|
const bodyContentUsed = effectiveContentHeight - remainingHeight;
|
|
@@ -1179,19 +1336,19 @@ var DocxodusPagination = (() => {
|
|
|
1179
1336
|
}
|
|
1180
1337
|
}
|
|
1181
1338
|
if (blockSpace <= effectiveRemainingHeight) {
|
|
1182
|
-
currentContent.push(
|
|
1339
|
+
currentContent.push(this.cloneBlockForPage(block, isFirstOnPage, pageInSection));
|
|
1183
1340
|
remainingHeight -= effectiveMarginTop + block.heightPt + block.marginBottomPt;
|
|
1184
1341
|
prevMarginBottomPt = block.marginBottomPt;
|
|
1185
1342
|
if (newFootnoteIds.length > 0) {
|
|
1186
1343
|
currentFootnoteIds.push(...newFootnoteIds);
|
|
1187
1344
|
currentFootnoteHeight += additionalFootnoteHeight;
|
|
1188
1345
|
}
|
|
1189
|
-
} else if (block.heightPt + block
|
|
1346
|
+
} else if (block.heightPt + this.effectiveBlockMarginTop(block, 0, true, pageInSection + 1) <= effectiveContentHeight) {
|
|
1190
1347
|
const blockSpaceWithoutFootnotes = effectiveMarginTop + block.heightPt;
|
|
1191
1348
|
const minBodySpaceNeeded = bodyContentUsed + blockSpaceWithoutFootnotes + MIN_BODY_CONTENT_HEIGHT;
|
|
1192
1349
|
const canExpandFootnotes = minBodySpaceNeeded <= effectiveContentHeight;
|
|
1193
1350
|
if (newFootnoteIds.length > 0 && blockSpaceWithoutFootnotes <= effectiveRemainingHeight) {
|
|
1194
|
-
currentContent.push(
|
|
1351
|
+
currentContent.push(this.cloneBlockForPage(block, isFirstOnPage, pageInSection));
|
|
1195
1352
|
remainingHeight -= effectiveMarginTop + block.heightPt + block.marginBottomPt;
|
|
1196
1353
|
prevMarginBottomPt = block.marginBottomPt;
|
|
1197
1354
|
const availableForFootnotes = Math.min(
|
|
@@ -1238,7 +1395,7 @@ var DocxodusPagination = (() => {
|
|
|
1238
1395
|
const expandedFootnoteSpace = Math.min(maxFootnoteArea, additionalFootnoteHeight + currentFootnoteHeight);
|
|
1239
1396
|
const bodySpaceAfterExpansion = effectiveContentHeight - expandedFootnoteSpace;
|
|
1240
1397
|
if (blockSpaceWithoutFootnotes <= bodySpaceAfterExpansion - bodyContentUsed) {
|
|
1241
|
-
currentContent.push(
|
|
1398
|
+
currentContent.push(this.cloneBlockForPage(block, isFirstOnPage, pageInSection));
|
|
1242
1399
|
remainingHeight = bodySpaceAfterExpansion - bodyContentUsed - blockSpaceWithoutFootnotes;
|
|
1243
1400
|
prevMarginBottomPt = block.marginBottomPt;
|
|
1244
1401
|
currentFootnoteIds.push(...newFootnoteIds);
|
|
@@ -1246,8 +1403,14 @@ var DocxodusPagination = (() => {
|
|
|
1246
1403
|
} else {
|
|
1247
1404
|
finishPage();
|
|
1248
1405
|
const newPageFootnoteHeight = allBlockFootnoteIds.length > 0 ? this.measureFootnotesHeight(allBlockFootnoteIds, dims.contentWidth, currentContinuation) : currentContinuation ? this.measureContinuationHeight(currentContinuation, dims.contentWidth) : 0;
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1406
|
+
const newPageMarginTop = this.effectiveBlockMarginTop(
|
|
1407
|
+
block,
|
|
1408
|
+
0,
|
|
1409
|
+
true,
|
|
1410
|
+
pageInSection
|
|
1411
|
+
);
|
|
1412
|
+
const newPageSpace = newPageMarginTop + block.heightPt + block.marginBottomPt;
|
|
1413
|
+
currentContent.push(this.cloneBlockForPage(block, true, pageInSection));
|
|
1251
1414
|
remainingHeight = effectiveContentHeight - newPageSpace;
|
|
1252
1415
|
prevMarginBottomPt = block.marginBottomPt;
|
|
1253
1416
|
currentFootnoteIds = [...currentFootnoteIds, ...allBlockFootnoteIds];
|
|
@@ -1256,8 +1419,14 @@ var DocxodusPagination = (() => {
|
|
|
1256
1419
|
} else {
|
|
1257
1420
|
finishPage();
|
|
1258
1421
|
const newPageFootnoteHeight = allBlockFootnoteIds.length > 0 ? this.measureFootnotesHeight(allBlockFootnoteIds, dims.contentWidth, currentContinuation) : currentContinuation ? this.measureContinuationHeight(currentContinuation, dims.contentWidth) : 0;
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1422
|
+
const newPageMarginTop = this.effectiveBlockMarginTop(
|
|
1423
|
+
block,
|
|
1424
|
+
0,
|
|
1425
|
+
true,
|
|
1426
|
+
pageInSection
|
|
1427
|
+
);
|
|
1428
|
+
const newPageSpace = newPageMarginTop + block.heightPt + block.marginBottomPt;
|
|
1429
|
+
currentContent.push(this.cloneBlockForPage(block, true, pageInSection));
|
|
1261
1430
|
remainingHeight = effectiveContentHeight - newPageSpace;
|
|
1262
1431
|
prevMarginBottomPt = block.marginBottomPt;
|
|
1263
1432
|
currentFootnoteIds = [...currentFootnoteIds, ...allBlockFootnoteIds];
|
|
@@ -1276,7 +1445,7 @@ var DocxodusPagination = (() => {
|
|
|
1276
1445
|
if (currentContent.length > 0) {
|
|
1277
1446
|
finishPage();
|
|
1278
1447
|
}
|
|
1279
|
-
currentContent.push(
|
|
1448
|
+
currentContent.push(this.cloneBlockForPage(block, true, pageInSection));
|
|
1280
1449
|
currentFootnoteIds = [...currentFootnoteIds, ...allBlockFootnoteIds];
|
|
1281
1450
|
finishPage();
|
|
1282
1451
|
}
|
|
@@ -1306,6 +1475,161 @@ var DocxodusPagination = (() => {
|
|
|
1306
1475
|
if (el.getAttribute("contenteditable") !== null) el.setAttribute("contenteditable", "false");
|
|
1307
1476
|
}
|
|
1308
1477
|
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Resolves floating DrawingML objects after their anchor paragraphs have landed on a page.
|
|
1480
|
+
*
|
|
1481
|
+
* The converter deliberately carries the OOXML bases and offsets as data instead of flattening
|
|
1482
|
+
* them into CSS: page/margin/column bases belong to the page, while paragraph/line/character
|
|
1483
|
+
* bases belong to the laid-out anchor. Once both coordinate systems exist, promote the object
|
|
1484
|
+
* from the clipped text column into the page box and position it in one shared point space.
|
|
1485
|
+
*/
|
|
1486
|
+
positionDrawingAnchors(pageBox, contentArea, dims, pageNumber) {
|
|
1487
|
+
const anchors = Array.from(
|
|
1488
|
+
contentArea.querySelectorAll('[data-docx-drawing-anchor="true"]')
|
|
1489
|
+
);
|
|
1490
|
+
if (anchors.length === 0) return;
|
|
1491
|
+
const pageRect = pageBox.getBoundingClientRect();
|
|
1492
|
+
const pixelsPerPoint = pageRect.width / dims.pageWidth;
|
|
1493
|
+
if (!(pixelsPerPoint > 0)) return;
|
|
1494
|
+
for (const anchor of anchors) {
|
|
1495
|
+
const staticRect = anchor.getBoundingClientRect();
|
|
1496
|
+
const paragraph = anchor.closest("p, h1, h2, h3, h4, h5, h6");
|
|
1497
|
+
const paragraphRect = paragraph?.getBoundingClientRect() ?? staticRect;
|
|
1498
|
+
const toPageX = (x) => (x - pageRect.left) / pixelsPerPoint;
|
|
1499
|
+
const toPageY = (y) => (y - pageRect.top) / pixelsPerPoint;
|
|
1500
|
+
const context = {
|
|
1501
|
+
staticLeft: toPageX(staticRect.left),
|
|
1502
|
+
staticTop: toPageY(staticRect.top),
|
|
1503
|
+
lineHeight: paragraph ? (parseFloat(getComputedStyle(paragraph).lineHeight) || staticRect.height) / pixelsPerPoint : staticRect.height / pixelsPerPoint,
|
|
1504
|
+
paragraphLeft: toPageX(paragraphRect.left),
|
|
1505
|
+
paragraphTop: toPageY(paragraphRect.top),
|
|
1506
|
+
paragraphWidth: paragraphRect.width / pixelsPerPoint,
|
|
1507
|
+
paragraphHeight: paragraphRect.height / pixelsPerPoint
|
|
1508
|
+
};
|
|
1509
|
+
const widthReference = this.horizontalAnchorReference(
|
|
1510
|
+
anchor.getAttribute("data-docx-anchor-width-relative") ?? "margin",
|
|
1511
|
+
dims,
|
|
1512
|
+
pageNumber,
|
|
1513
|
+
context
|
|
1514
|
+
);
|
|
1515
|
+
const widthPercent = this.anchorNumber(anchor, "width-percent");
|
|
1516
|
+
if (widthPercent !== void 0) {
|
|
1517
|
+
anchor.style.width = `${widthReference.size * widthPercent / 100}pt`;
|
|
1518
|
+
}
|
|
1519
|
+
const heightReference = this.verticalAnchorReference(
|
|
1520
|
+
anchor.getAttribute("data-docx-anchor-height-relative") ?? "margin",
|
|
1521
|
+
dims,
|
|
1522
|
+
pageNumber,
|
|
1523
|
+
context
|
|
1524
|
+
);
|
|
1525
|
+
const heightPercent = this.anchorNumber(anchor, "height-percent");
|
|
1526
|
+
if (heightPercent !== void 0 && anchor.dataset.docxAnchorAutofit !== "true") {
|
|
1527
|
+
anchor.style.height = `${heightReference.size * heightPercent / 100}pt`;
|
|
1528
|
+
}
|
|
1529
|
+
const sizedRect = anchor.getBoundingClientRect();
|
|
1530
|
+
const width = sizedRect.width / pixelsPerPoint;
|
|
1531
|
+
const height = sizedRect.height / pixelsPerPoint;
|
|
1532
|
+
const horizontal = this.horizontalAnchorReference(
|
|
1533
|
+
anchor.getAttribute("data-docx-anchor-h-relative") ?? "column",
|
|
1534
|
+
dims,
|
|
1535
|
+
pageNumber,
|
|
1536
|
+
context
|
|
1537
|
+
);
|
|
1538
|
+
const vertical = this.verticalAnchorReference(
|
|
1539
|
+
anchor.getAttribute("data-docx-anchor-v-relative") ?? "paragraph",
|
|
1540
|
+
dims,
|
|
1541
|
+
pageNumber,
|
|
1542
|
+
context
|
|
1543
|
+
);
|
|
1544
|
+
const left = this.resolveAnchorAxis(
|
|
1545
|
+
horizontal,
|
|
1546
|
+
width,
|
|
1547
|
+
anchor.getAttribute("data-docx-anchor-h-align"),
|
|
1548
|
+
this.anchorNumber(anchor, "h-offset"),
|
|
1549
|
+
pageNumber
|
|
1550
|
+
);
|
|
1551
|
+
const top = this.resolveAnchorAxis(
|
|
1552
|
+
vertical,
|
|
1553
|
+
height,
|
|
1554
|
+
anchor.getAttribute("data-docx-anchor-v-align"),
|
|
1555
|
+
this.anchorNumber(anchor, "v-offset"),
|
|
1556
|
+
pageNumber
|
|
1557
|
+
);
|
|
1558
|
+
pageBox.appendChild(anchor);
|
|
1559
|
+
anchor.style.position = "absolute";
|
|
1560
|
+
anchor.style.left = `${left}pt`;
|
|
1561
|
+
anchor.style.top = `${top}pt`;
|
|
1562
|
+
anchor.style.margin = "0";
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
anchorNumber(anchor, suffix) {
|
|
1566
|
+
const raw = anchor.getAttribute(`data-docx-anchor-${suffix}`);
|
|
1567
|
+
if (raw === null) return void 0;
|
|
1568
|
+
const value = Number(raw);
|
|
1569
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1570
|
+
}
|
|
1571
|
+
horizontalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
1572
|
+
const leftMargin = { start: 0, size: dims.marginLeft };
|
|
1573
|
+
const rightMargin = {
|
|
1574
|
+
start: dims.marginLeft + dims.contentWidth,
|
|
1575
|
+
size: dims.marginRight
|
|
1576
|
+
};
|
|
1577
|
+
switch (relativeFrom) {
|
|
1578
|
+
case "page":
|
|
1579
|
+
return { start: 0, size: dims.pageWidth };
|
|
1580
|
+
case "character":
|
|
1581
|
+
return { start: context.staticLeft, size: 0 };
|
|
1582
|
+
case "leftMargin":
|
|
1583
|
+
return leftMargin;
|
|
1584
|
+
case "rightMargin":
|
|
1585
|
+
return rightMargin;
|
|
1586
|
+
case "insideMargin":
|
|
1587
|
+
return pageNumber % 2 === 1 ? leftMargin : rightMargin;
|
|
1588
|
+
case "outsideMargin":
|
|
1589
|
+
return pageNumber % 2 === 1 ? rightMargin : leftMargin;
|
|
1590
|
+
case "paragraph":
|
|
1591
|
+
return { start: context.paragraphLeft, size: context.paragraphWidth };
|
|
1592
|
+
case "column":
|
|
1593
|
+
case "margin":
|
|
1594
|
+
default:
|
|
1595
|
+
return { start: dims.marginLeft, size: dims.contentWidth };
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
verticalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
1599
|
+
const topMargin = { start: 0, size: dims.marginTop };
|
|
1600
|
+
const bottomMargin = {
|
|
1601
|
+
start: dims.marginTop + dims.contentHeight,
|
|
1602
|
+
size: dims.marginBottom
|
|
1603
|
+
};
|
|
1604
|
+
switch (relativeFrom) {
|
|
1605
|
+
case "page":
|
|
1606
|
+
return { start: 0, size: dims.pageHeight };
|
|
1607
|
+
case "paragraph":
|
|
1608
|
+
return { start: context.paragraphTop, size: context.paragraphHeight };
|
|
1609
|
+
case "line":
|
|
1610
|
+
return { start: context.staticTop, size: context.lineHeight };
|
|
1611
|
+
case "topMargin":
|
|
1612
|
+
return topMargin;
|
|
1613
|
+
case "bottomMargin":
|
|
1614
|
+
return bottomMargin;
|
|
1615
|
+
case "insideMargin":
|
|
1616
|
+
return pageNumber % 2 === 1 ? topMargin : bottomMargin;
|
|
1617
|
+
case "outsideMargin":
|
|
1618
|
+
return pageNumber % 2 === 1 ? bottomMargin : topMargin;
|
|
1619
|
+
case "margin":
|
|
1620
|
+
default:
|
|
1621
|
+
return { start: dims.marginTop, size: dims.contentHeight };
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
resolveAnchorAxis(reference, objectSize, alignment, offset, pageNumber) {
|
|
1625
|
+
if (offset !== void 0) return reference.start + offset;
|
|
1626
|
+
let fraction = 0;
|
|
1627
|
+
if (alignment === "center") fraction = 0.5;
|
|
1628
|
+
else if (alignment === "right" || alignment === "bottom") fraction = 1;
|
|
1629
|
+
else if (alignment === "inside") fraction = pageNumber % 2 === 1 ? 0 : 1;
|
|
1630
|
+
else if (alignment === "outside") fraction = pageNumber % 2 === 1 ? 1 : 0;
|
|
1631
|
+
return reference.start + (reference.size - objectSize) * fraction;
|
|
1632
|
+
}
|
|
1309
1633
|
/**
|
|
1310
1634
|
* Creates a page container element.
|
|
1311
1635
|
*/
|
|
@@ -1332,22 +1656,22 @@ var DocxodusPagination = (() => {
|
|
|
1332
1656
|
pageBox.dataset.pageNumber = String(pageNumber);
|
|
1333
1657
|
pageBox.dataset.sectionIndex = String(sectionIndex);
|
|
1334
1658
|
pageBox.dataset.pageInSection = String(pageInSection);
|
|
1335
|
-
const
|
|
1659
|
+
const bands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
1336
1660
|
const headerSource = this.selectHeader(sectionIndex, pageInSection, pageNumber);
|
|
1337
1661
|
if (headerSource) {
|
|
1338
1662
|
const headerDiv = document.createElement("div");
|
|
1339
1663
|
headerDiv.className = `${this.cssPrefix}header`;
|
|
1340
1664
|
headerDiv.style.position = "absolute";
|
|
1341
|
-
headerDiv.style.top =
|
|
1665
|
+
headerDiv.style.top = `${bands.headerTop}pt`;
|
|
1666
|
+
headerDiv.style.bottom = "auto";
|
|
1342
1667
|
headerDiv.style.left = `${dims.marginLeft}pt`;
|
|
1343
1668
|
headerDiv.style.width = `${dims.contentWidth}pt`;
|
|
1344
|
-
headerDiv.style.height = `${
|
|
1669
|
+
headerDiv.style.height = `${bands.headerHeight}pt`;
|
|
1345
1670
|
headerDiv.style.overflow = "hidden";
|
|
1346
1671
|
headerDiv.style.boxSizing = "border-box";
|
|
1347
1672
|
headerDiv.style.display = "flex";
|
|
1348
1673
|
headerDiv.style.flexDirection = "column";
|
|
1349
|
-
headerDiv.style.justifyContent = "flex-
|
|
1350
|
-
headerDiv.style.paddingBottom = "4pt";
|
|
1674
|
+
headerDiv.style.justifyContent = "flex-start";
|
|
1351
1675
|
for (const child of Array.from(headerSource.childNodes)) {
|
|
1352
1676
|
const clonedheaderDiv = child.cloneNode(true);
|
|
1353
1677
|
if (clonedheaderDiv.nodeType === 1) this.makeClonedStoryInert(clonedheaderDiv);
|
|
@@ -1355,8 +1679,8 @@ var DocxodusPagination = (() => {
|
|
|
1355
1679
|
}
|
|
1356
1680
|
pageBox.appendChild(headerDiv);
|
|
1357
1681
|
}
|
|
1358
|
-
const contentAreaTop =
|
|
1359
|
-
const contentAreaHeight =
|
|
1682
|
+
const contentAreaTop = bands.bodyTop;
|
|
1683
|
+
const contentAreaHeight = bands.bodyHeight;
|
|
1360
1684
|
const contentArea = document.createElement("div");
|
|
1361
1685
|
contentArea.className = `${this.cssPrefix}content`;
|
|
1362
1686
|
contentArea.style.position = "absolute";
|
|
@@ -1371,23 +1695,23 @@ var DocxodusPagination = (() => {
|
|
|
1371
1695
|
pageBox.appendChild(contentArea);
|
|
1372
1696
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
1373
1697
|
if (footnoteIds.length > 0 || hasContinuation) {
|
|
1374
|
-
this.addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes);
|
|
1698
|
+
this.addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes);
|
|
1375
1699
|
}
|
|
1376
1700
|
const footerSource = this.selectFooter(sectionIndex, pageInSection, pageNumber);
|
|
1377
1701
|
if (footerSource) {
|
|
1378
1702
|
const footerDiv = document.createElement("div");
|
|
1379
1703
|
footerDiv.className = `${this.cssPrefix}footer`;
|
|
1380
1704
|
footerDiv.style.position = "absolute";
|
|
1381
|
-
footerDiv.style.
|
|
1705
|
+
footerDiv.style.top = "auto";
|
|
1706
|
+
footerDiv.style.bottom = `${dims.footerDistance}pt`;
|
|
1382
1707
|
footerDiv.style.left = `${dims.marginLeft}pt`;
|
|
1383
1708
|
footerDiv.style.width = `${dims.contentWidth}pt`;
|
|
1384
|
-
footerDiv.style.height = `${
|
|
1709
|
+
footerDiv.style.height = `${bands.footerHeight}pt`;
|
|
1385
1710
|
footerDiv.style.overflow = "hidden";
|
|
1386
1711
|
footerDiv.style.boxSizing = "border-box";
|
|
1387
1712
|
footerDiv.style.display = "flex";
|
|
1388
1713
|
footerDiv.style.flexDirection = "column";
|
|
1389
|
-
footerDiv.style.justifyContent = "flex-
|
|
1390
|
-
footerDiv.style.paddingTop = "4pt";
|
|
1714
|
+
footerDiv.style.justifyContent = "flex-end";
|
|
1391
1715
|
for (const child of Array.from(footerSource.childNodes)) {
|
|
1392
1716
|
const clonedfooterDiv = child.cloneNode(true);
|
|
1393
1717
|
if (clonedfooterDiv.nodeType === 1) this.makeClonedStoryInert(clonedfooterDiv);
|
|
@@ -1402,6 +1726,7 @@ var DocxodusPagination = (() => {
|
|
|
1402
1726
|
pageBox.appendChild(pageNum);
|
|
1403
1727
|
}
|
|
1404
1728
|
this.containerElement.appendChild(pageBox);
|
|
1729
|
+
this.positionDrawingAnchors(pageBox, contentArea, dims, pageNumber);
|
|
1405
1730
|
const notesEl = pageBox.querySelector(`.${this.cssPrefix}footnotes`);
|
|
1406
1731
|
if (notesEl) {
|
|
1407
1732
|
const notesHeightPt = pxToPt(notesEl.getBoundingClientRect().height);
|