@softwear/latestcollectioncore 1.0.184 → 1.0.186
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/.prettierrc.json +2 -2
- package/dist/pdf.d.ts +4 -1
- package/dist/reports.js +35 -73
- package/package.json +1 -1
- package/src/pdf.ts +4 -1
- package/src/reports.ts +45 -155
package/.prettierrc.json
CHANGED
package/dist/pdf.d.ts
CHANGED
|
@@ -54,7 +54,10 @@ export interface ContainerLayoutObject extends BaseLayoutObject {
|
|
|
54
54
|
minHeightBeforeBreak?: number;
|
|
55
55
|
/** When true, container and children are drawn only once at the end of the report, not on every page */
|
|
56
56
|
printOnlyAtEnd?: boolean;
|
|
57
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Only on top-level `layout.objects`. Same intent as onlyRenderOnFirstPage: drawn once on the first printable page,
|
|
59
|
+
* not repeated after overflow page breaks.
|
|
60
|
+
*/
|
|
58
61
|
printOnlyAtStart?: boolean;
|
|
59
62
|
}
|
|
60
63
|
export type LayoutObject = TextLayoutObject | FieldLayoutObject | RectangleLayoutObject | ImageLayoutObject | ContainerLayoutObject;
|
package/dist/reports.js
CHANGED
|
@@ -16,6 +16,14 @@ exports.genPDF = void 0;
|
|
|
16
16
|
const jspdf_1 = require("jspdf");
|
|
17
17
|
const date_fns_1 = require("date-fns");
|
|
18
18
|
const deepCopy_1 = __importDefault(require("./deepCopy"));
|
|
19
|
+
/** Measurement uses context `currentPageNumber` (1-based). Rendering normalizes jsPDF’s internal 0-based page index to 1-based so overlap rules match `pageNumber` fields. */
|
|
20
|
+
function getCurrentPageNumber(doc, context) {
|
|
21
|
+
var _a;
|
|
22
|
+
if (context.mode === 'measurement') {
|
|
23
|
+
return (_a = context.currentPageNumber) !== null && _a !== void 0 ? _a : 1;
|
|
24
|
+
}
|
|
25
|
+
return doc.getCurrentPageInfo().pageNumber + 1;
|
|
26
|
+
}
|
|
19
27
|
// We have to declare some functions that will be called by other functions but also have to call those other functions
|
|
20
28
|
// We overwrite the function definition as soon as those other functions have been declared
|
|
21
29
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
@@ -24,7 +32,7 @@ let drawStaticPartOfPage = function (doc, layout, printBuffer, paperSize, option
|
|
|
24
32
|
};
|
|
25
33
|
// Forward declaration - parameters intentionally unused, function is overwritten below
|
|
26
34
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
27
|
-
let addObjectToPDF = function (_originX, _originY, _doc, _object, _printBuffer, _paperSize, _layout, _options, _rootPrintBuffer, _containerChain, _context) {
|
|
35
|
+
let addObjectToPDF = function (_originX, _originY, _doc, _object, _printBuffer, _paperSize, _layout, _options, _rootPrintBuffer, _containerChain, _context, _printOnlyAtStartContainersOffset) {
|
|
28
36
|
// to be assigned later
|
|
29
37
|
return { x: 0, y: 0 };
|
|
30
38
|
};
|
|
@@ -400,18 +408,12 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
400
408
|
}
|
|
401
409
|
}
|
|
402
410
|
function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, containerChain, context) {
|
|
411
|
+
var _a;
|
|
403
412
|
/** Absolute tenths where the overflowing repeat resumes; callers already computed this correctly. */
|
|
404
413
|
const continuationOxTenths = originX;
|
|
405
414
|
const continuationOyTenths = originY;
|
|
406
|
-
context.pendingRootStartBumpTenths = 0;
|
|
407
|
-
context.applyRootStartBumpToThisCall = false;
|
|
408
|
-
context.remainingRootStartBumpTenths = 0;
|
|
409
415
|
if (context.mode === 'measurement') {
|
|
410
|
-
|
|
411
|
-
if (context.currentPageCount === undefined) {
|
|
412
|
-
context.currentPageCount = 1;
|
|
413
|
-
}
|
|
414
|
-
context.currentPageCount++;
|
|
416
|
+
context.currentPageNumber = ((_a = context.currentPageNumber) !== null && _a !== void 0 ? _a : 1) + 1;
|
|
415
417
|
}
|
|
416
418
|
else if (!context.measureOnly) {
|
|
417
419
|
// Actually add page in rendering mode (skip when measuring for fillContainer)
|
|
@@ -438,10 +440,7 @@ function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, opti
|
|
|
438
440
|
if (child.snapToBottom)
|
|
439
441
|
return;
|
|
440
442
|
// Skip inner repeat container on chain: advancing origin by x,y is enough; the live loop draws rows.
|
|
441
|
-
if (child.type === 'container' &&
|
|
442
|
-
deeperLinkChild &&
|
|
443
|
-
child === deeperLinkChild &&
|
|
444
|
-
!containerRedrawsAfterContinuationPage(child)) {
|
|
443
|
+
if (child.type === 'container' && deeperLinkChild && child === deeperLinkChild && !containerRedrawsAfterContinuationPage(child)) {
|
|
445
444
|
const c = child;
|
|
446
445
|
originX += c.x;
|
|
447
446
|
originY += c.y;
|
|
@@ -503,49 +502,35 @@ function drawBottomDwellers(object, originX, originY, absoluteLowerRightHandSide
|
|
|
503
502
|
*
|
|
504
503
|
* Use originX,originY as origin to displace the object's own x,y coordinates
|
|
505
504
|
*/
|
|
506
|
-
addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize, layout, options, rootPrintBuffer, containerChain, context) {
|
|
507
|
-
var _a
|
|
508
|
-
if (context.applyRootStartBumpToThisCall) {
|
|
509
|
-
context.remainingRootStartBumpTenths = (_a = context.pendingRootStartBumpTenths) !== null && _a !== void 0 ? _a : 0;
|
|
510
|
-
context.applyRootStartBumpToThisCall = false;
|
|
511
|
-
context.pendingRootStartBumpTenths = 0;
|
|
512
|
-
}
|
|
505
|
+
addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize, layout, options, rootPrintBuffer, containerChain, context, printOnlyAtStartContainersOffset) {
|
|
506
|
+
var _a;
|
|
513
507
|
const layoutXtenths = originX + object.x;
|
|
514
508
|
const layoutYtenths = originY + object.y;
|
|
515
|
-
|
|
516
|
-
const
|
|
509
|
+
const rawPrintOnlyAtStartOffset = printOnlyAtStartContainersOffset !== null && printOnlyAtStartContainersOffset !== void 0 ? printOnlyAtStartContainersOffset : 0;
|
|
510
|
+
const effectivePrintOnlyAtStartContainersOffset = containerChain.length === 0 && rawPrintOnlyAtStartOffset > 0 && getCurrentPageNumber(doc, context) === 1 ? rawPrintOnlyAtStartOffset : 0;
|
|
517
511
|
const x = layoutXtenths / 10;
|
|
518
|
-
const y = (layoutYtenths +
|
|
512
|
+
const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10;
|
|
519
513
|
const width = object.width / 10;
|
|
520
514
|
const height = object.height / 10;
|
|
521
515
|
// Keep track of the lower righthandside of all objects in this container
|
|
522
516
|
// We need to return this object so whatever calls addObjectToPDF knows how big our drawing was
|
|
523
517
|
let absoluteLowerRightHandSide = { x: x + width, y: y + height };
|
|
524
518
|
if (!object.active) {
|
|
525
|
-
if (bumpForDrawNonContainer !== 0)
|
|
526
|
-
context.remainingRootStartBumpTenths = 0;
|
|
527
519
|
return absoluteLowerRightHandSide;
|
|
528
520
|
}
|
|
529
521
|
if (object.type != 'container') {
|
|
530
|
-
if (bumpForDrawNonContainer !== 0)
|
|
531
|
-
context.remainingRootStartBumpTenths = 0;
|
|
532
522
|
drawSimpleObject(x, y, doc, object, printBuffer, width, height, options, context);
|
|
533
523
|
}
|
|
534
524
|
// Recursively draw all child objects from a container object
|
|
535
525
|
if (object.type == 'container') {
|
|
536
526
|
const source = containerLoopSource(object, printBuffer);
|
|
537
527
|
if (source === undefined) {
|
|
538
|
-
(
|
|
539
|
-
if (containerChain.length === 0)
|
|
540
|
-
context.remainingRootStartBumpTenths = 0;
|
|
528
|
+
(_a = options.onAlert) === null || _a === void 0 ? void 0 : _a.call(options, { header: 'containernotfound', body: object.source, type: 'warning', timeout: 10000 });
|
|
541
529
|
return absoluteLowerRightHandSide;
|
|
542
530
|
}
|
|
543
531
|
const nrContainers = source.length;
|
|
544
|
-
let bumpOnce = containerChain.length === 0 ? (_d = context.remainingRootStartBumpTenths) !== null && _d !== void 0 ? _d : 0 : 0;
|
|
545
|
-
if (bumpOnce !== 0 && containerChain.length === 0)
|
|
546
|
-
context.remainingRootStartBumpTenths = 0;
|
|
547
532
|
let originX = layoutXtenths;
|
|
548
|
-
let originY = layoutYtenths +
|
|
533
|
+
let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
|
|
549
534
|
for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
|
|
550
535
|
const newContainerChain = containerChain.filter(function () {
|
|
551
536
|
return true;
|
|
@@ -557,7 +542,7 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
|
|
|
557
542
|
if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
|
|
558
543
|
// We ran out of paper
|
|
559
544
|
originX = layoutXtenths;
|
|
560
|
-
originY = layoutYtenths +
|
|
545
|
+
originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
|
|
561
546
|
const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context);
|
|
562
547
|
originX = newOrigin.originX;
|
|
563
548
|
originY = newOrigin.originY;
|
|
@@ -731,10 +716,12 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
731
716
|
paperSize.width *= 10;
|
|
732
717
|
paperSize.height *= 10;
|
|
733
718
|
paperSize.footerHeight *= 10;
|
|
734
|
-
// First pass: Measurement mode
|
|
719
|
+
// First pass: Measurement mode — page count without visible output; overlaps must match render pass inputs.
|
|
735
720
|
const measurementContext = {
|
|
736
721
|
mode: 'measurement',
|
|
737
|
-
|
|
722
|
+
currentPageNumber: 1,
|
|
723
|
+
imageAssets,
|
|
724
|
+
defaultFontFamily: layout.defaultFontFamily,
|
|
738
725
|
};
|
|
739
726
|
// Create a minimal jsPDF instance for measurement (needed for some calculations)
|
|
740
727
|
const measurementDoc = new jspdf_1.jsPDF({
|
|
@@ -747,37 +734,26 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
747
734
|
}
|
|
748
735
|
drawStaticPartOfPage(measurementDoc, layout, printBuffer, paperSize, options, measurementContext);
|
|
749
736
|
// Draw containers in measurement mode (same order as render)
|
|
750
|
-
|
|
737
|
+
/** Max lower edge (layout units ×10 = tenths-mm) of print-only-at-start roots; deterministic for fixed layout+buffer once measure uses same context as render. */
|
|
738
|
+
let measuredPrintOnlyAtStartOffset = 0;
|
|
751
739
|
layout.objects
|
|
752
740
|
.filter((object) => object.type == 'container' && object.printOnlyAtStart === true)
|
|
753
741
|
.forEach((object) => {
|
|
754
742
|
const lh = addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
755
|
-
|
|
743
|
+
measuredPrintOnlyAtStartOffset = Math.max(measuredPrintOnlyAtStartOffset, lh.y * 10);
|
|
756
744
|
});
|
|
757
745
|
layout.objects
|
|
758
|
-
.filter((object) => object.type == 'container' &&
|
|
759
|
-
object.printOnlyAtEnd !== true &&
|
|
760
|
-
object.printOnlyAtStart !== true)
|
|
746
|
+
.filter((object) => object.type == 'container' && object.printOnlyAtEnd !== true && object.printOnlyAtStart !== true)
|
|
761
747
|
.forEach((object) => {
|
|
762
|
-
|
|
763
|
-
if (bumpTenths > 0) {
|
|
764
|
-
measurementContext.applyRootStartBumpToThisCall = true;
|
|
765
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths;
|
|
766
|
-
}
|
|
767
|
-
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
748
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y));
|
|
768
749
|
});
|
|
769
750
|
layout.objects
|
|
770
751
|
.filter((object) => object.type == 'container' && object.printOnlyAtEnd === true)
|
|
771
752
|
.forEach((object) => {
|
|
772
|
-
|
|
773
|
-
if (bumpTenths > 0) {
|
|
774
|
-
measurementContext.applyRootStartBumpToThisCall = true;
|
|
775
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths;
|
|
776
|
-
}
|
|
777
|
-
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
753
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y));
|
|
778
754
|
});
|
|
779
755
|
// Get total page count from measurement pass
|
|
780
|
-
const totalPageCount = measurementContext.
|
|
756
|
+
const totalPageCount = measurementContext.currentPageNumber || 1;
|
|
781
757
|
// Second pass: Rendering mode - actual PDF generation with pageCount available
|
|
782
758
|
const doc = new jspdf_1.jsPDF({
|
|
783
759
|
orientation: paperSizeCopy.width > paperSizeCopy.height ? 'landscape' : 'portrait',
|
|
@@ -793,35 +769,21 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
793
769
|
defaultFontFamily: layout.defaultFontFamily,
|
|
794
770
|
};
|
|
795
771
|
drawStaticPartOfPage(doc, layout, printBuffer, paperSize, options, renderContext);
|
|
796
|
-
let renderTopPrintedStartBottomTenths = 0;
|
|
797
772
|
layout.objects
|
|
798
773
|
.filter((object) => object.type == 'container' && object.printOnlyAtStart === true)
|
|
799
774
|
.forEach((object) => {
|
|
800
|
-
|
|
801
|
-
renderTopPrintedStartBottomTenths = Math.max(renderTopPrintedStartBottomTenths, lh.y * 10);
|
|
775
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
802
776
|
});
|
|
803
777
|
// Draw containers in rendering mode (body containers after printOnlyAtStart)
|
|
804
778
|
layout.objects
|
|
805
|
-
.filter((object) => object.type == 'container' &&
|
|
806
|
-
object.printOnlyAtEnd !== true &&
|
|
807
|
-
object.printOnlyAtStart !== true)
|
|
779
|
+
.filter((object) => object.type == 'container' && object.printOnlyAtEnd !== true && object.printOnlyAtStart !== true)
|
|
808
780
|
.forEach((object) => {
|
|
809
|
-
|
|
810
|
-
if (bumpTenths > 0) {
|
|
811
|
-
renderContext.applyRootStartBumpToThisCall = true;
|
|
812
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths;
|
|
813
|
-
}
|
|
814
|
-
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
781
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y));
|
|
815
782
|
});
|
|
816
783
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
817
784
|
const printOnlyAtEndContainers = layout.objects.filter((object) => object.type == 'container' && object.printOnlyAtEnd === true);
|
|
818
785
|
printOnlyAtEndContainers.forEach((object) => {
|
|
819
|
-
|
|
820
|
-
if (bumpTenths > 0) {
|
|
821
|
-
renderContext.applyRootStartBumpToThisCall = true;
|
|
822
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths;
|
|
823
|
-
}
|
|
824
|
-
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
786
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y));
|
|
825
787
|
});
|
|
826
788
|
return doc;
|
|
827
789
|
});
|
package/package.json
CHANGED
package/src/pdf.ts
CHANGED
|
@@ -61,7 +61,10 @@ export interface ContainerLayoutObject extends BaseLayoutObject {
|
|
|
61
61
|
minHeightBeforeBreak?: number
|
|
62
62
|
/** When true, container and children are drawn only once at the end of the report, not on every page */
|
|
63
63
|
printOnlyAtEnd?: boolean
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Only on top-level `layout.objects`. Same intent as onlyRenderOnFirstPage: drawn once on the first printable page,
|
|
66
|
+
* not repeated after overflow page breaks.
|
|
67
|
+
*/
|
|
65
68
|
printOnlyAtStart?: boolean
|
|
66
69
|
}
|
|
67
70
|
|
package/src/reports.ts
CHANGED
|
@@ -40,20 +40,22 @@ export interface GenPdfOptions {
|
|
|
40
40
|
|
|
41
41
|
interface RenderContext {
|
|
42
42
|
mode: RenderMode
|
|
43
|
+
/** Total pages from measurement pass; used for field sources like `pageCount` / `page`. */
|
|
43
44
|
pageCount?: number
|
|
44
|
-
|
|
45
|
+
/** During measurement, logical printable page (starts at 1); incremented when {@link addPage} runs. Rendering: see {@link getCurrentPageNumber} (1-based, matches pdf page fields). */
|
|
46
|
+
currentPageNumber?: number
|
|
45
47
|
measureOnly?: boolean // When true, skip drawing to measure bounds (for fillContainer rectangles)
|
|
46
48
|
imageAssets?: Map<string, PdfImageAsset>
|
|
47
49
|
/** Layout default font used when object.fontFamily is undefined */
|
|
48
50
|
defaultFontFamily?: string
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Measurement uses context `currentPageNumber` (1-based). Rendering normalizes jsPDF’s internal 0-based page index to 1-based so overlap rules match `pageNumber` fields. */
|
|
54
|
+
function getCurrentPageNumber(doc: jsPDF, context: RenderContext): number {
|
|
55
|
+
if (context.mode === 'measurement') {
|
|
56
|
+
return context.currentPageNumber ?? 1
|
|
57
|
+
}
|
|
58
|
+
return doc.getCurrentPageInfo().pageNumber + 1
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
// We have to declare some functions that will be called by other functions but also have to call those other functions
|
|
@@ -76,7 +78,8 @@ let addObjectToPDF = function (
|
|
|
76
78
|
_options: GenPdfOptions,
|
|
77
79
|
_rootPrintBuffer: any,
|
|
78
80
|
_containerChain: { object: ContainerLayoutObject; printBuffer: any }[],
|
|
79
|
-
_context: RenderContext
|
|
81
|
+
_context: RenderContext,
|
|
82
|
+
_printOnlyAtStartContainersOffset?: number
|
|
80
83
|
): { x: number; y: number } {
|
|
81
84
|
// to be assigned later
|
|
82
85
|
return { x: 0, y: 0 }
|
|
@@ -123,17 +126,8 @@ function containerLoopSource(container: ContainerLayoutObject, printBuffer: any)
|
|
|
123
126
|
* They are not on the nested {@link containerChain}; redraw them whenever we append a continuation page.
|
|
124
127
|
* Omit the overflowing root when it is chain[0] — redrawing it would recurse (e.g. wrapper around lines).
|
|
125
128
|
*/
|
|
126
|
-
function redrawRootDummyBodyContainersOnNewPage(
|
|
127
|
-
|
|
128
|
-
layout: Layout,
|
|
129
|
-
rootPrintBuffer: any,
|
|
130
|
-
paperSize: PaperSize,
|
|
131
|
-
options: GenPdfOptions,
|
|
132
|
-
context: RenderContext,
|
|
133
|
-
containerChain: { object: ContainerLayoutObject; printBuffer: any }[]
|
|
134
|
-
): void {
|
|
135
|
-
const overflowingRootContainer =
|
|
136
|
-
containerChain.length > 0 ? (containerChain[0].object as ContainerLayoutObject) : undefined
|
|
129
|
+
function redrawRootDummyBodyContainersOnNewPage(doc: jsPDF, layout: Layout, rootPrintBuffer: any, paperSize: PaperSize, options: GenPdfOptions, context: RenderContext, containerChain: { object: ContainerLayoutObject; printBuffer: any }[]): void {
|
|
130
|
+
const overflowingRootContainer = containerChain.length > 0 ? (containerChain[0].object as ContainerLayoutObject) : undefined
|
|
137
131
|
|
|
138
132
|
layout.objects.forEach((object) => {
|
|
139
133
|
if (object.type !== 'container') return
|
|
@@ -333,17 +327,7 @@ function truncateTextToFitWidth(doc: jsPDF, text: string, maxWidth: number): str
|
|
|
333
327
|
return truncatedText + ELLIPSIS
|
|
334
328
|
}
|
|
335
329
|
|
|
336
|
-
function drawSimpleObject(
|
|
337
|
-
x: number,
|
|
338
|
-
y: number,
|
|
339
|
-
doc: jsPDF,
|
|
340
|
-
object: LayoutObject,
|
|
341
|
-
printBuffer: any,
|
|
342
|
-
width: number,
|
|
343
|
-
height: number,
|
|
344
|
-
options: GenPdfOptions,
|
|
345
|
-
context: RenderContext
|
|
346
|
-
): void {
|
|
330
|
+
function drawSimpleObject(x: number, y: number, doc: jsPDF, object: LayoutObject, printBuffer: any, width: number, height: number, options: GenPdfOptions, context: RenderContext): void {
|
|
347
331
|
let text = '' // Will hold text to display for either 'text' or 'field'
|
|
348
332
|
|
|
349
333
|
// Get text from object for text objects
|
|
@@ -484,15 +468,8 @@ function addPage(
|
|
|
484
468
|
const continuationOxTenths = originX
|
|
485
469
|
const continuationOyTenths = originY
|
|
486
470
|
|
|
487
|
-
context.pendingRootStartBumpTenths = 0
|
|
488
|
-
context.applyRootStartBumpToThisCall = false
|
|
489
|
-
context.remainingRootStartBumpTenths = 0
|
|
490
471
|
if (context.mode === 'measurement') {
|
|
491
|
-
|
|
492
|
-
if (context.currentPageCount === undefined) {
|
|
493
|
-
context.currentPageCount = 1
|
|
494
|
-
}
|
|
495
|
-
context.currentPageCount++
|
|
472
|
+
context.currentPageNumber = (context.currentPageNumber ?? 1) + 1
|
|
496
473
|
} else if (!context.measureOnly) {
|
|
497
474
|
// Actually add page in rendering mode (skip when measuring for fillContainer)
|
|
498
475
|
doc.addPage()
|
|
@@ -517,12 +494,7 @@ function addPage(
|
|
|
517
494
|
link.object.children.forEach((child) => {
|
|
518
495
|
if (child.snapToBottom) return
|
|
519
496
|
// Skip inner repeat container on chain: advancing origin by x,y is enough; the live loop draws rows.
|
|
520
|
-
if (
|
|
521
|
-
child.type === 'container' &&
|
|
522
|
-
deeperLinkChild &&
|
|
523
|
-
child === deeperLinkChild &&
|
|
524
|
-
!containerRedrawsAfterContinuationPage(child)
|
|
525
|
-
) {
|
|
497
|
+
if (child.type === 'container' && deeperLinkChild && child === deeperLinkChild && !containerRedrawsAfterContinuationPage(child)) {
|
|
526
498
|
const c = child as ContainerLayoutObject
|
|
527
499
|
originX += c.x
|
|
528
500
|
originY += c.y
|
|
@@ -607,21 +579,17 @@ addObjectToPDF = function (
|
|
|
607
579
|
options: GenPdfOptions,
|
|
608
580
|
rootPrintBuffer: any,
|
|
609
581
|
containerChain: { object: ContainerLayoutObject; printBuffer: any }[],
|
|
610
|
-
context: RenderContext
|
|
582
|
+
context: RenderContext,
|
|
583
|
+
printOnlyAtStartContainersOffset?: number
|
|
611
584
|
): { x: number; y: number } {
|
|
612
|
-
if (context.applyRootStartBumpToThisCall) {
|
|
613
|
-
context.remainingRootStartBumpTenths = context.pendingRootStartBumpTenths ?? 0
|
|
614
|
-
context.applyRootStartBumpToThisCall = false
|
|
615
|
-
context.pendingRootStartBumpTenths = 0
|
|
616
|
-
}
|
|
617
585
|
const layoutXtenths = originX + object.x
|
|
618
586
|
const layoutYtenths = originY + object.y
|
|
619
|
-
|
|
620
|
-
const
|
|
621
|
-
containerChain.length === 0
|
|
587
|
+
const rawPrintOnlyAtStartOffset = printOnlyAtStartContainersOffset ?? 0
|
|
588
|
+
const effectivePrintOnlyAtStartContainersOffset =
|
|
589
|
+
containerChain.length === 0 && rawPrintOnlyAtStartOffset > 0 && getCurrentPageNumber(doc, context) === 1 ? rawPrintOnlyAtStartOffset : 0
|
|
622
590
|
|
|
623
591
|
const x = layoutXtenths / 10
|
|
624
|
-
const y = (layoutYtenths +
|
|
592
|
+
const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10
|
|
625
593
|
const width = object.width / 10
|
|
626
594
|
const height = object.height / 10
|
|
627
595
|
// Keep track of the lower righthandside of all objects in this container
|
|
@@ -629,11 +597,9 @@ addObjectToPDF = function (
|
|
|
629
597
|
let absoluteLowerRightHandSide = { x: x + width, y: y + height }
|
|
630
598
|
|
|
631
599
|
if (!object.active) {
|
|
632
|
-
if (bumpForDrawNonContainer !== 0) context.remainingRootStartBumpTenths = 0
|
|
633
600
|
return absoluteLowerRightHandSide
|
|
634
601
|
}
|
|
635
602
|
if (object.type != 'container') {
|
|
636
|
-
if (bumpForDrawNonContainer !== 0) context.remainingRootStartBumpTenths = 0
|
|
637
603
|
drawSimpleObject(x, y, doc, object, printBuffer, width, height, options, context)
|
|
638
604
|
}
|
|
639
605
|
|
|
@@ -642,15 +608,12 @@ addObjectToPDF = function (
|
|
|
642
608
|
const source = containerLoopSource(object as ContainerLayoutObject, printBuffer)
|
|
643
609
|
if (source === undefined) {
|
|
644
610
|
options.onAlert?.({ header: 'containernotfound', body: object.source, type: 'warning', timeout: 10000 })
|
|
645
|
-
if (containerChain.length === 0) context.remainingRootStartBumpTenths = 0
|
|
646
611
|
return absoluteLowerRightHandSide
|
|
647
612
|
}
|
|
648
613
|
const nrContainers = source.length
|
|
649
614
|
|
|
650
|
-
let bumpOnce = containerChain.length === 0 ? context.remainingRootStartBumpTenths ?? 0 : 0
|
|
651
|
-
if (bumpOnce !== 0 && containerChain.length === 0) context.remainingRootStartBumpTenths = 0
|
|
652
615
|
let originX = layoutXtenths
|
|
653
|
-
let originY = layoutYtenths +
|
|
616
|
+
let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
|
|
654
617
|
|
|
655
618
|
for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
|
|
656
619
|
const newContainerChain = containerChain.filter(function () {
|
|
@@ -663,7 +626,7 @@ addObjectToPDF = function (
|
|
|
663
626
|
if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
|
|
664
627
|
// We ran out of paper
|
|
665
628
|
originX = layoutXtenths
|
|
666
|
-
originY = layoutYtenths +
|
|
629
|
+
originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
|
|
667
630
|
const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context)
|
|
668
631
|
originX = newOrigin.originX
|
|
669
632
|
originY = newOrigin.originY
|
|
@@ -694,21 +657,7 @@ addObjectToPDF = function (
|
|
|
694
657
|
measureBounds.y = Math.max(measureBounds.y, r.y)
|
|
695
658
|
}
|
|
696
659
|
})
|
|
697
|
-
const measureBottom = drawBottomDwellers(
|
|
698
|
-
object as ContainerLayoutObject,
|
|
699
|
-
measureOriginX,
|
|
700
|
-
measureOriginY,
|
|
701
|
-
{ x: measureBounds.x, y: measureBounds.y },
|
|
702
|
-
measureBottomChildY,
|
|
703
|
-
paperSize,
|
|
704
|
-
doc,
|
|
705
|
-
layout,
|
|
706
|
-
rootPrintBuffer,
|
|
707
|
-
options,
|
|
708
|
-
measureChain,
|
|
709
|
-
container,
|
|
710
|
-
measureContext
|
|
711
|
-
)
|
|
660
|
+
const measureBottom = drawBottomDwellers(object as ContainerLayoutObject, measureOriginX, measureOriginY, { x: measureBounds.x, y: measureBounds.y }, measureBottomChildY, paperSize, doc, layout, rootPrintBuffer, options, measureChain, container, measureContext)
|
|
712
661
|
measureBounds.y = Math.max(measureBounds.y, measureBottom.y)
|
|
713
662
|
// Draw fillContainer rectangles as background
|
|
714
663
|
fillContainerRects.forEach(function (rect: any) {
|
|
@@ -776,42 +725,14 @@ addObjectToPDF = function (
|
|
|
776
725
|
originX = newOrigin.originX
|
|
777
726
|
originY = newOrigin.originY
|
|
778
727
|
absoluteLowerRightHandSide = { x: newOrigin.x, y: newOrigin.y }
|
|
779
|
-
const newestOrigin = drawBottomDwellers(
|
|
780
|
-
object as ContainerLayoutObject,
|
|
781
|
-
originX,
|
|
782
|
-
originY,
|
|
783
|
-
absoluteLowerRightHandSide,
|
|
784
|
-
bottomChildY,
|
|
785
|
-
paperSize,
|
|
786
|
-
doc,
|
|
787
|
-
layout,
|
|
788
|
-
rootPrintBuffer,
|
|
789
|
-
options,
|
|
790
|
-
newContainerChain,
|
|
791
|
-
container,
|
|
792
|
-
context
|
|
793
|
-
)
|
|
728
|
+
const newestOrigin = drawBottomDwellers(object as ContainerLayoutObject, originX, originY, absoluteLowerRightHandSide, bottomChildY, paperSize, doc, layout, rootPrintBuffer, options, newContainerChain, container, context)
|
|
794
729
|
originX = newestOrigin.originX
|
|
795
730
|
originY = newestOrigin.originY
|
|
796
731
|
absoluteLowerRightHandSide = { x: newestOrigin.x, y: newestOrigin.y }
|
|
797
732
|
continue
|
|
798
733
|
}
|
|
799
734
|
}
|
|
800
|
-
const newestOrigin = drawBottomDwellers(
|
|
801
|
-
object as ContainerLayoutObject,
|
|
802
|
-
originX,
|
|
803
|
-
originY,
|
|
804
|
-
absoluteLowerRightHandSide,
|
|
805
|
-
bottomChildY,
|
|
806
|
-
paperSize,
|
|
807
|
-
doc,
|
|
808
|
-
layout,
|
|
809
|
-
rootPrintBuffer,
|
|
810
|
-
options,
|
|
811
|
-
newContainerChain,
|
|
812
|
-
container,
|
|
813
|
-
context
|
|
814
|
-
)
|
|
735
|
+
const newestOrigin = drawBottomDwellers(object as ContainerLayoutObject, originX, originY, absoluteLowerRightHandSide, bottomChildY, paperSize, doc, layout, rootPrintBuffer, options, newContainerChain, container, context)
|
|
815
736
|
originX = newestOrigin.originX
|
|
816
737
|
originY = newestOrigin.originY
|
|
817
738
|
absoluteLowerRightHandSide = { x: newestOrigin.x, y: newestOrigin.y }
|
|
@@ -870,10 +791,12 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
870
791
|
paperSize.height *= 10
|
|
871
792
|
paperSize.footerHeight *= 10
|
|
872
793
|
|
|
873
|
-
// First pass: Measurement mode
|
|
794
|
+
// First pass: Measurement mode — page count without visible output; overlaps must match render pass inputs.
|
|
874
795
|
const measurementContext: RenderContext = {
|
|
875
796
|
mode: 'measurement',
|
|
876
|
-
|
|
797
|
+
currentPageNumber: 1,
|
|
798
|
+
imageAssets,
|
|
799
|
+
defaultFontFamily: layout.defaultFontFamily,
|
|
877
800
|
}
|
|
878
801
|
// Create a minimal jsPDF instance for measurement (needed for some calculations)
|
|
879
802
|
const measurementDoc = new jsPDF({
|
|
@@ -887,41 +810,27 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
887
810
|
drawStaticPartOfPage(measurementDoc, layout, printBuffer, paperSize, options, measurementContext)
|
|
888
811
|
|
|
889
812
|
// Draw containers in measurement mode (same order as render)
|
|
890
|
-
|
|
813
|
+
/** Max lower edge (layout units ×10 = tenths-mm) of print-only-at-start roots; deterministic for fixed layout+buffer once measure uses same context as render. */
|
|
814
|
+
let measuredPrintOnlyAtStartOffset = 0
|
|
891
815
|
layout.objects
|
|
892
816
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtStart === true)
|
|
893
817
|
.forEach((object) => {
|
|
894
818
|
const lh = addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
895
|
-
|
|
819
|
+
measuredPrintOnlyAtStartOffset = Math.max(measuredPrintOnlyAtStartOffset, lh.y * 10)
|
|
896
820
|
})
|
|
897
821
|
layout.objects
|
|
898
|
-
.filter(
|
|
899
|
-
(object) =>
|
|
900
|
-
object.type == 'container' &&
|
|
901
|
-
(object as ContainerLayoutObject).printOnlyAtEnd !== true &&
|
|
902
|
-
(object as ContainerLayoutObject).printOnlyAtStart !== true
|
|
903
|
-
)
|
|
822
|
+
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd !== true && (object as ContainerLayoutObject).printOnlyAtStart !== true)
|
|
904
823
|
.forEach((object) => {
|
|
905
|
-
|
|
906
|
-
if (bumpTenths > 0) {
|
|
907
|
-
measurementContext.applyRootStartBumpToThisCall = true
|
|
908
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths
|
|
909
|
-
}
|
|
910
|
-
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
824
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y))
|
|
911
825
|
})
|
|
912
826
|
layout.objects
|
|
913
827
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true)
|
|
914
828
|
.forEach((object) => {
|
|
915
|
-
|
|
916
|
-
if (bumpTenths > 0) {
|
|
917
|
-
measurementContext.applyRootStartBumpToThisCall = true
|
|
918
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths
|
|
919
|
-
}
|
|
920
|
-
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
829
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y))
|
|
921
830
|
})
|
|
922
831
|
|
|
923
832
|
// Get total page count from measurement pass
|
|
924
|
-
const totalPageCount = measurementContext.
|
|
833
|
+
const totalPageCount = measurementContext.currentPageNumber || 1
|
|
925
834
|
|
|
926
835
|
// Second pass: Rendering mode - actual PDF generation with pageCount available
|
|
927
836
|
const doc = new jsPDF({
|
|
@@ -939,42 +848,23 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
939
848
|
}
|
|
940
849
|
drawStaticPartOfPage(doc, layout, printBuffer, paperSize, options, renderContext)
|
|
941
850
|
|
|
942
|
-
let renderTopPrintedStartBottomTenths = 0
|
|
943
851
|
layout.objects
|
|
944
852
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtStart === true)
|
|
945
853
|
.forEach((object) => {
|
|
946
|
-
|
|
947
|
-
renderTopPrintedStartBottomTenths = Math.max(renderTopPrintedStartBottomTenths, lh.y * 10)
|
|
854
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
948
855
|
})
|
|
949
856
|
|
|
950
857
|
// Draw containers in rendering mode (body containers after printOnlyAtStart)
|
|
951
858
|
layout.objects
|
|
952
|
-
.filter(
|
|
953
|
-
(object) =>
|
|
954
|
-
object.type == 'container' &&
|
|
955
|
-
(object as ContainerLayoutObject).printOnlyAtEnd !== true &&
|
|
956
|
-
(object as ContainerLayoutObject).printOnlyAtStart !== true
|
|
957
|
-
)
|
|
859
|
+
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd !== true && (object as ContainerLayoutObject).printOnlyAtStart !== true)
|
|
958
860
|
.forEach((object) => {
|
|
959
|
-
|
|
960
|
-
if (bumpTenths > 0) {
|
|
961
|
-
renderContext.applyRootStartBumpToThisCall = true
|
|
962
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths
|
|
963
|
-
}
|
|
964
|
-
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
861
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y))
|
|
965
862
|
})
|
|
966
863
|
|
|
967
864
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
968
|
-
const printOnlyAtEndContainers = layout.objects.filter(
|
|
969
|
-
(object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true
|
|
970
|
-
)
|
|
865
|
+
const printOnlyAtEndContainers = layout.objects.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true)
|
|
971
866
|
printOnlyAtEndContainers.forEach((object) => {
|
|
972
|
-
|
|
973
|
-
if (bumpTenths > 0) {
|
|
974
|
-
renderContext.applyRootStartBumpToThisCall = true
|
|
975
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths
|
|
976
|
-
}
|
|
977
|
-
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
867
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext, Math.max(0, measuredPrintOnlyAtStartOffset - object.y))
|
|
978
868
|
})
|
|
979
869
|
return doc
|
|
980
870
|
}
|