@softwear/latestcollectioncore 1.0.183 → 1.0.185
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 +56 -73
- package/package.json +1 -1
- package/src/pdf.ts +4 -1
- package/src/reports.ts +62 -144
- package/test/reports.spec.ts +68 -0
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 never advances jsPDF sheet count; rendering uses the active canvas page (1-based). */
|
|
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;
|
|
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
|
};
|
|
@@ -61,6 +69,26 @@ function containerLoopSource(container, printBuffer) {
|
|
|
61
69
|
return [printBuffer];
|
|
62
70
|
return getProperty(container.source, printBuffer);
|
|
63
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Top-level empty-source containers (invoice “billTo” bands, wrappers) sit beside overflowing repeats.
|
|
74
|
+
* They are not on the nested {@link containerChain}; redraw them whenever we append a continuation page.
|
|
75
|
+
* Omit the overflowing root when it is chain[0] — redrawing it would recurse (e.g. wrapper around lines).
|
|
76
|
+
*/
|
|
77
|
+
function redrawRootDummyBodyContainersOnNewPage(doc, layout, rootPrintBuffer, paperSize, options, context, containerChain) {
|
|
78
|
+
const overflowingRootContainer = containerChain.length > 0 ? containerChain[0].object : undefined;
|
|
79
|
+
layout.objects.forEach((object) => {
|
|
80
|
+
if (object.type !== 'container')
|
|
81
|
+
return;
|
|
82
|
+
if (overflowingRootContainer !== undefined && object === overflowingRootContainer)
|
|
83
|
+
return;
|
|
84
|
+
const c = object;
|
|
85
|
+
if (c.printOnlyAtStart === true || c.printOnlyAtEnd === true)
|
|
86
|
+
return;
|
|
87
|
+
if (!dummyLayoutSource(c.source))
|
|
88
|
+
return;
|
|
89
|
+
addObjectToPDF(0, 0, doc, object, rootPrintBuffer, paperSize, layout, options, rootPrintBuffer, [], context);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
64
92
|
/** jsPDF font style strings. fontStyle bitmask: 0=normal, 1=bold, 2=italic, 3=bold+italic */
|
|
65
93
|
const FONT_STYLES = ['normal', 'bold', 'italic', 'bolditalic'];
|
|
66
94
|
/** Recursively collect used custom fonts from layout objects (text/field with fontFamily) and layout default. */
|
|
@@ -380,18 +408,12 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
380
408
|
}
|
|
381
409
|
}
|
|
382
410
|
function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, containerChain, context) {
|
|
411
|
+
var _a;
|
|
383
412
|
/** Absolute tenths where the overflowing repeat resumes; callers already computed this correctly. */
|
|
384
413
|
const continuationOxTenths = originX;
|
|
385
414
|
const continuationOyTenths = originY;
|
|
386
|
-
context.pendingRootStartBumpTenths = 0;
|
|
387
|
-
context.applyRootStartBumpToThisCall = false;
|
|
388
|
-
context.remainingRootStartBumpTenths = 0;
|
|
389
415
|
if (context.mode === 'measurement') {
|
|
390
|
-
|
|
391
|
-
if (context.currentPageCount === undefined) {
|
|
392
|
-
context.currentPageCount = 1;
|
|
393
|
-
}
|
|
394
|
-
context.currentPageCount++;
|
|
416
|
+
context.currentPageNumber = ((_a = context.currentPageNumber) !== null && _a !== void 0 ? _a : 1) + 1;
|
|
395
417
|
}
|
|
396
418
|
else if (!context.measureOnly) {
|
|
397
419
|
// Actually add page in rendering mode (skip when measuring for fillContainer)
|
|
@@ -399,6 +421,7 @@ function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, opti
|
|
|
399
421
|
}
|
|
400
422
|
if (!context.measureOnly) {
|
|
401
423
|
drawStaticPartOfPage(doc, layout, rootPrintBuffer, paperSize, options, context);
|
|
424
|
+
redrawRootDummyBodyContainersOnNewPage(doc, layout, rootPrintBuffer, paperSize, options, context, containerChain);
|
|
402
425
|
}
|
|
403
426
|
// Bounding box tracked for snap-to-bottom; continuation cursor is ALWAYS the passed-in coords.
|
|
404
427
|
const absoluteLowerRightHandSide = { x: continuationOxTenths / 10, y: continuationOyTenths / 10 };
|
|
@@ -417,10 +440,7 @@ function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, opti
|
|
|
417
440
|
if (child.snapToBottom)
|
|
418
441
|
return;
|
|
419
442
|
// Skip inner repeat container on chain: advancing origin by x,y is enough; the live loop draws rows.
|
|
420
|
-
if (child.type === 'container' &&
|
|
421
|
-
deeperLinkChild &&
|
|
422
|
-
child === deeperLinkChild &&
|
|
423
|
-
!containerRedrawsAfterContinuationPage(child)) {
|
|
443
|
+
if (child.type === 'container' && deeperLinkChild && child === deeperLinkChild && !containerRedrawsAfterContinuationPage(child)) {
|
|
424
444
|
const c = child;
|
|
425
445
|
originX += c.x;
|
|
426
446
|
originY += c.y;
|
|
@@ -482,49 +502,35 @@ function drawBottomDwellers(object, originX, originY, absoluteLowerRightHandSide
|
|
|
482
502
|
*
|
|
483
503
|
* Use originX,originY as origin to displace the object's own x,y coordinates
|
|
484
504
|
*/
|
|
485
|
-
addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize, layout, options, rootPrintBuffer, containerChain, context) {
|
|
486
|
-
var _a
|
|
487
|
-
if (context.applyRootStartBumpToThisCall) {
|
|
488
|
-
context.remainingRootStartBumpTenths = (_a = context.pendingRootStartBumpTenths) !== null && _a !== void 0 ? _a : 0;
|
|
489
|
-
context.applyRootStartBumpToThisCall = false;
|
|
490
|
-
context.pendingRootStartBumpTenths = 0;
|
|
491
|
-
}
|
|
505
|
+
addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize, layout, options, rootPrintBuffer, containerChain, context, printOnlyAtStartContainersOffset) {
|
|
506
|
+
var _a;
|
|
492
507
|
const layoutXtenths = originX + object.x;
|
|
493
508
|
const layoutYtenths = originY + object.y;
|
|
494
|
-
|
|
495
|
-
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;
|
|
496
511
|
const x = layoutXtenths / 10;
|
|
497
|
-
const y = (layoutYtenths +
|
|
512
|
+
const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10;
|
|
498
513
|
const width = object.width / 10;
|
|
499
514
|
const height = object.height / 10;
|
|
500
515
|
// Keep track of the lower righthandside of all objects in this container
|
|
501
516
|
// We need to return this object so whatever calls addObjectToPDF knows how big our drawing was
|
|
502
517
|
let absoluteLowerRightHandSide = { x: x + width, y: y + height };
|
|
503
518
|
if (!object.active) {
|
|
504
|
-
if (bumpForDrawNonContainer !== 0)
|
|
505
|
-
context.remainingRootStartBumpTenths = 0;
|
|
506
519
|
return absoluteLowerRightHandSide;
|
|
507
520
|
}
|
|
508
521
|
if (object.type != 'container') {
|
|
509
|
-
if (bumpForDrawNonContainer !== 0)
|
|
510
|
-
context.remainingRootStartBumpTenths = 0;
|
|
511
522
|
drawSimpleObject(x, y, doc, object, printBuffer, width, height, options, context);
|
|
512
523
|
}
|
|
513
524
|
// Recursively draw all child objects from a container object
|
|
514
525
|
if (object.type == 'container') {
|
|
515
526
|
const source = containerLoopSource(object, printBuffer);
|
|
516
527
|
if (source === undefined) {
|
|
517
|
-
(
|
|
518
|
-
if (containerChain.length === 0)
|
|
519
|
-
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 });
|
|
520
529
|
return absoluteLowerRightHandSide;
|
|
521
530
|
}
|
|
522
531
|
const nrContainers = source.length;
|
|
523
|
-
let bumpOnce = containerChain.length === 0 ? (_d = context.remainingRootStartBumpTenths) !== null && _d !== void 0 ? _d : 0 : 0;
|
|
524
|
-
if (bumpOnce !== 0 && containerChain.length === 0)
|
|
525
|
-
context.remainingRootStartBumpTenths = 0;
|
|
526
532
|
let originX = layoutXtenths;
|
|
527
|
-
let originY = layoutYtenths +
|
|
533
|
+
let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
|
|
528
534
|
for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
|
|
529
535
|
const newContainerChain = containerChain.filter(function () {
|
|
530
536
|
return true;
|
|
@@ -536,7 +542,7 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
|
|
|
536
542
|
if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
|
|
537
543
|
// We ran out of paper
|
|
538
544
|
originX = layoutXtenths;
|
|
539
|
-
originY = layoutYtenths +
|
|
545
|
+
originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
|
|
540
546
|
const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context);
|
|
541
547
|
originX = newOrigin.originX;
|
|
542
548
|
originY = newOrigin.originY;
|
|
@@ -710,10 +716,12 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
710
716
|
paperSize.width *= 10;
|
|
711
717
|
paperSize.height *= 10;
|
|
712
718
|
paperSize.footerHeight *= 10;
|
|
713
|
-
// First pass: Measurement mode
|
|
719
|
+
// First pass: Measurement mode — page count without visible output; overlaps must match render pass inputs.
|
|
714
720
|
const measurementContext = {
|
|
715
721
|
mode: 'measurement',
|
|
716
|
-
|
|
722
|
+
currentPageNumber: 1,
|
|
723
|
+
imageAssets,
|
|
724
|
+
defaultFontFamily: layout.defaultFontFamily,
|
|
717
725
|
};
|
|
718
726
|
// Create a minimal jsPDF instance for measurement (needed for some calculations)
|
|
719
727
|
const measurementDoc = new jspdf_1.jsPDF({
|
|
@@ -726,37 +734,26 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
726
734
|
}
|
|
727
735
|
drawStaticPartOfPage(measurementDoc, layout, printBuffer, paperSize, options, measurementContext);
|
|
728
736
|
// Draw containers in measurement mode (same order as render)
|
|
729
|
-
|
|
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;
|
|
730
739
|
layout.objects
|
|
731
740
|
.filter((object) => object.type == 'container' && object.printOnlyAtStart === true)
|
|
732
741
|
.forEach((object) => {
|
|
733
742
|
const lh = addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
734
|
-
|
|
743
|
+
measuredPrintOnlyAtStartOffset = Math.max(measuredPrintOnlyAtStartOffset, lh.y * 10);
|
|
735
744
|
});
|
|
736
745
|
layout.objects
|
|
737
|
-
.filter((object) => object.type == 'container' &&
|
|
738
|
-
object.printOnlyAtEnd !== true &&
|
|
739
|
-
object.printOnlyAtStart !== true)
|
|
746
|
+
.filter((object) => object.type == 'container' && object.printOnlyAtEnd !== true && object.printOnlyAtStart !== true)
|
|
740
747
|
.forEach((object) => {
|
|
741
|
-
|
|
742
|
-
if (bumpTenths > 0) {
|
|
743
|
-
measurementContext.applyRootStartBumpToThisCall = true;
|
|
744
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths;
|
|
745
|
-
}
|
|
746
|
-
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));
|
|
747
749
|
});
|
|
748
750
|
layout.objects
|
|
749
751
|
.filter((object) => object.type == 'container' && object.printOnlyAtEnd === true)
|
|
750
752
|
.forEach((object) => {
|
|
751
|
-
|
|
752
|
-
if (bumpTenths > 0) {
|
|
753
|
-
measurementContext.applyRootStartBumpToThisCall = true;
|
|
754
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths;
|
|
755
|
-
}
|
|
756
|
-
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));
|
|
757
754
|
});
|
|
758
755
|
// Get total page count from measurement pass
|
|
759
|
-
const totalPageCount = measurementContext.
|
|
756
|
+
const totalPageCount = measurementContext.currentPageNumber || 1;
|
|
760
757
|
// Second pass: Rendering mode - actual PDF generation with pageCount available
|
|
761
758
|
const doc = new jspdf_1.jsPDF({
|
|
762
759
|
orientation: paperSizeCopy.width > paperSizeCopy.height ? 'landscape' : 'portrait',
|
|
@@ -772,35 +769,21 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
772
769
|
defaultFontFamily: layout.defaultFontFamily,
|
|
773
770
|
};
|
|
774
771
|
drawStaticPartOfPage(doc, layout, printBuffer, paperSize, options, renderContext);
|
|
775
|
-
let renderTopPrintedStartBottomTenths = 0;
|
|
776
772
|
layout.objects
|
|
777
773
|
.filter((object) => object.type == 'container' && object.printOnlyAtStart === true)
|
|
778
774
|
.forEach((object) => {
|
|
779
|
-
|
|
780
|
-
renderTopPrintedStartBottomTenths = Math.max(renderTopPrintedStartBottomTenths, lh.y * 10);
|
|
775
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
781
776
|
});
|
|
782
777
|
// Draw containers in rendering mode (body containers after printOnlyAtStart)
|
|
783
778
|
layout.objects
|
|
784
|
-
.filter((object) => object.type == 'container' &&
|
|
785
|
-
object.printOnlyAtEnd !== true &&
|
|
786
|
-
object.printOnlyAtStart !== true)
|
|
779
|
+
.filter((object) => object.type == 'container' && object.printOnlyAtEnd !== true && object.printOnlyAtStart !== true)
|
|
787
780
|
.forEach((object) => {
|
|
788
|
-
|
|
789
|
-
if (bumpTenths > 0) {
|
|
790
|
-
renderContext.applyRootStartBumpToThisCall = true;
|
|
791
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths;
|
|
792
|
-
}
|
|
793
|
-
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));
|
|
794
782
|
});
|
|
795
783
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
796
784
|
const printOnlyAtEndContainers = layout.objects.filter((object) => object.type == 'container' && object.printOnlyAtEnd === true);
|
|
797
785
|
printOnlyAtEndContainers.forEach((object) => {
|
|
798
|
-
|
|
799
|
-
if (bumpTenths > 0) {
|
|
800
|
-
renderContext.applyRootStartBumpToThisCall = true;
|
|
801
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths;
|
|
802
|
-
}
|
|
803
|
-
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));
|
|
804
787
|
});
|
|
805
788
|
return doc;
|
|
806
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. In rendering use {@link getCurrentPageNumber} (jsPDF). */
|
|
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 never advances jsPDF sheet count; rendering uses the active canvas page (1-based). */
|
|
54
|
+
function getCurrentPageNumber(doc: jsPDF, context: RenderContext): number {
|
|
55
|
+
if (context.mode === 'measurement') {
|
|
56
|
+
return context.currentPageNumber ?? 1
|
|
57
|
+
}
|
|
58
|
+
return doc.getCurrentPageInfo().pageNumber
|
|
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 }
|
|
@@ -118,6 +121,24 @@ function containerLoopSource(container: ContainerLayoutObject, printBuffer: any)
|
|
|
118
121
|
return getProperty(container.source as string, printBuffer)
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Top-level empty-source containers (invoice “billTo” bands, wrappers) sit beside overflowing repeats.
|
|
126
|
+
* They are not on the nested {@link containerChain}; redraw them whenever we append a continuation page.
|
|
127
|
+
* Omit the overflowing root when it is chain[0] — redrawing it would recurse (e.g. wrapper around lines).
|
|
128
|
+
*/
|
|
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
|
|
131
|
+
|
|
132
|
+
layout.objects.forEach((object) => {
|
|
133
|
+
if (object.type !== 'container') return
|
|
134
|
+
if (overflowingRootContainer !== undefined && object === overflowingRootContainer) return
|
|
135
|
+
const c = object as ContainerLayoutObject
|
|
136
|
+
if (c.printOnlyAtStart === true || c.printOnlyAtEnd === true) return
|
|
137
|
+
if (!dummyLayoutSource(c.source)) return
|
|
138
|
+
addObjectToPDF(0, 0, doc, object, rootPrintBuffer, paperSize, layout, options, rootPrintBuffer, [], context)
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
121
142
|
/** jsPDF font style strings. fontStyle bitmask: 0=normal, 1=bold, 2=italic, 3=bold+italic */
|
|
122
143
|
const FONT_STYLES = ['normal', 'bold', 'italic', 'bolditalic'] as const
|
|
123
144
|
|
|
@@ -306,17 +327,7 @@ function truncateTextToFitWidth(doc: jsPDF, text: string, maxWidth: number): str
|
|
|
306
327
|
return truncatedText + ELLIPSIS
|
|
307
328
|
}
|
|
308
329
|
|
|
309
|
-
function drawSimpleObject(
|
|
310
|
-
x: number,
|
|
311
|
-
y: number,
|
|
312
|
-
doc: jsPDF,
|
|
313
|
-
object: LayoutObject,
|
|
314
|
-
printBuffer: any,
|
|
315
|
-
width: number,
|
|
316
|
-
height: number,
|
|
317
|
-
options: GenPdfOptions,
|
|
318
|
-
context: RenderContext
|
|
319
|
-
): void {
|
|
330
|
+
function drawSimpleObject(x: number, y: number, doc: jsPDF, object: LayoutObject, printBuffer: any, width: number, height: number, options: GenPdfOptions, context: RenderContext): void {
|
|
320
331
|
let text = '' // Will hold text to display for either 'text' or 'field'
|
|
321
332
|
|
|
322
333
|
// Get text from object for text objects
|
|
@@ -457,21 +468,15 @@ function addPage(
|
|
|
457
468
|
const continuationOxTenths = originX
|
|
458
469
|
const continuationOyTenths = originY
|
|
459
470
|
|
|
460
|
-
context.pendingRootStartBumpTenths = 0
|
|
461
|
-
context.applyRootStartBumpToThisCall = false
|
|
462
|
-
context.remainingRootStartBumpTenths = 0
|
|
463
471
|
if (context.mode === 'measurement') {
|
|
464
|
-
|
|
465
|
-
if (context.currentPageCount === undefined) {
|
|
466
|
-
context.currentPageCount = 1
|
|
467
|
-
}
|
|
468
|
-
context.currentPageCount++
|
|
472
|
+
context.currentPageNumber = (context.currentPageNumber ?? 1) + 1
|
|
469
473
|
} else if (!context.measureOnly) {
|
|
470
474
|
// Actually add page in rendering mode (skip when measuring for fillContainer)
|
|
471
475
|
doc.addPage()
|
|
472
476
|
}
|
|
473
477
|
if (!context.measureOnly) {
|
|
474
478
|
drawStaticPartOfPage(doc, layout, rootPrintBuffer, paperSize, options, context)
|
|
479
|
+
redrawRootDummyBodyContainersOnNewPage(doc, layout, rootPrintBuffer, paperSize, options, context, containerChain)
|
|
475
480
|
}
|
|
476
481
|
// Bounding box tracked for snap-to-bottom; continuation cursor is ALWAYS the passed-in coords.
|
|
477
482
|
const absoluteLowerRightHandSide = { x: continuationOxTenths / 10, y: continuationOyTenths / 10 }
|
|
@@ -489,12 +494,7 @@ function addPage(
|
|
|
489
494
|
link.object.children.forEach((child) => {
|
|
490
495
|
if (child.snapToBottom) return
|
|
491
496
|
// Skip inner repeat container on chain: advancing origin by x,y is enough; the live loop draws rows.
|
|
492
|
-
if (
|
|
493
|
-
child.type === 'container' &&
|
|
494
|
-
deeperLinkChild &&
|
|
495
|
-
child === deeperLinkChild &&
|
|
496
|
-
!containerRedrawsAfterContinuationPage(child)
|
|
497
|
-
) {
|
|
497
|
+
if (child.type === 'container' && deeperLinkChild && child === deeperLinkChild && !containerRedrawsAfterContinuationPage(child)) {
|
|
498
498
|
const c = child as ContainerLayoutObject
|
|
499
499
|
originX += c.x
|
|
500
500
|
originY += c.y
|
|
@@ -579,21 +579,17 @@ addObjectToPDF = function (
|
|
|
579
579
|
options: GenPdfOptions,
|
|
580
580
|
rootPrintBuffer: any,
|
|
581
581
|
containerChain: { object: ContainerLayoutObject; printBuffer: any }[],
|
|
582
|
-
context: RenderContext
|
|
582
|
+
context: RenderContext,
|
|
583
|
+
printOnlyAtStartContainersOffset?: number
|
|
583
584
|
): { x: number; y: number } {
|
|
584
|
-
if (context.applyRootStartBumpToThisCall) {
|
|
585
|
-
context.remainingRootStartBumpTenths = context.pendingRootStartBumpTenths ?? 0
|
|
586
|
-
context.applyRootStartBumpToThisCall = false
|
|
587
|
-
context.pendingRootStartBumpTenths = 0
|
|
588
|
-
}
|
|
589
585
|
const layoutXtenths = originX + object.x
|
|
590
586
|
const layoutYtenths = originY + object.y
|
|
591
|
-
|
|
592
|
-
const
|
|
593
|
-
containerChain.length === 0
|
|
587
|
+
const rawPrintOnlyAtStartOffset = printOnlyAtStartContainersOffset ?? 0
|
|
588
|
+
const effectivePrintOnlyAtStartContainersOffset =
|
|
589
|
+
containerChain.length === 0 && rawPrintOnlyAtStartOffset > 0 && getCurrentPageNumber(doc, context) === 1 ? rawPrintOnlyAtStartOffset : 0
|
|
594
590
|
|
|
595
591
|
const x = layoutXtenths / 10
|
|
596
|
-
const y = (layoutYtenths +
|
|
592
|
+
const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10
|
|
597
593
|
const width = object.width / 10
|
|
598
594
|
const height = object.height / 10
|
|
599
595
|
// Keep track of the lower righthandside of all objects in this container
|
|
@@ -601,11 +597,9 @@ addObjectToPDF = function (
|
|
|
601
597
|
let absoluteLowerRightHandSide = { x: x + width, y: y + height }
|
|
602
598
|
|
|
603
599
|
if (!object.active) {
|
|
604
|
-
if (bumpForDrawNonContainer !== 0) context.remainingRootStartBumpTenths = 0
|
|
605
600
|
return absoluteLowerRightHandSide
|
|
606
601
|
}
|
|
607
602
|
if (object.type != 'container') {
|
|
608
|
-
if (bumpForDrawNonContainer !== 0) context.remainingRootStartBumpTenths = 0
|
|
609
603
|
drawSimpleObject(x, y, doc, object, printBuffer, width, height, options, context)
|
|
610
604
|
}
|
|
611
605
|
|
|
@@ -614,15 +608,12 @@ addObjectToPDF = function (
|
|
|
614
608
|
const source = containerLoopSource(object as ContainerLayoutObject, printBuffer)
|
|
615
609
|
if (source === undefined) {
|
|
616
610
|
options.onAlert?.({ header: 'containernotfound', body: object.source, type: 'warning', timeout: 10000 })
|
|
617
|
-
if (containerChain.length === 0) context.remainingRootStartBumpTenths = 0
|
|
618
611
|
return absoluteLowerRightHandSide
|
|
619
612
|
}
|
|
620
613
|
const nrContainers = source.length
|
|
621
614
|
|
|
622
|
-
let bumpOnce = containerChain.length === 0 ? context.remainingRootStartBumpTenths ?? 0 : 0
|
|
623
|
-
if (bumpOnce !== 0 && containerChain.length === 0) context.remainingRootStartBumpTenths = 0
|
|
624
615
|
let originX = layoutXtenths
|
|
625
|
-
let originY = layoutYtenths +
|
|
616
|
+
let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
|
|
626
617
|
|
|
627
618
|
for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
|
|
628
619
|
const newContainerChain = containerChain.filter(function () {
|
|
@@ -635,7 +626,7 @@ addObjectToPDF = function (
|
|
|
635
626
|
if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
|
|
636
627
|
// We ran out of paper
|
|
637
628
|
originX = layoutXtenths
|
|
638
|
-
originY = layoutYtenths +
|
|
629
|
+
originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
|
|
639
630
|
const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context)
|
|
640
631
|
originX = newOrigin.originX
|
|
641
632
|
originY = newOrigin.originY
|
|
@@ -666,21 +657,7 @@ addObjectToPDF = function (
|
|
|
666
657
|
measureBounds.y = Math.max(measureBounds.y, r.y)
|
|
667
658
|
}
|
|
668
659
|
})
|
|
669
|
-
const measureBottom = drawBottomDwellers(
|
|
670
|
-
object as ContainerLayoutObject,
|
|
671
|
-
measureOriginX,
|
|
672
|
-
measureOriginY,
|
|
673
|
-
{ x: measureBounds.x, y: measureBounds.y },
|
|
674
|
-
measureBottomChildY,
|
|
675
|
-
paperSize,
|
|
676
|
-
doc,
|
|
677
|
-
layout,
|
|
678
|
-
rootPrintBuffer,
|
|
679
|
-
options,
|
|
680
|
-
measureChain,
|
|
681
|
-
container,
|
|
682
|
-
measureContext
|
|
683
|
-
)
|
|
660
|
+
const measureBottom = drawBottomDwellers(object as ContainerLayoutObject, measureOriginX, measureOriginY, { x: measureBounds.x, y: measureBounds.y }, measureBottomChildY, paperSize, doc, layout, rootPrintBuffer, options, measureChain, container, measureContext)
|
|
684
661
|
measureBounds.y = Math.max(measureBounds.y, measureBottom.y)
|
|
685
662
|
// Draw fillContainer rectangles as background
|
|
686
663
|
fillContainerRects.forEach(function (rect: any) {
|
|
@@ -748,42 +725,14 @@ addObjectToPDF = function (
|
|
|
748
725
|
originX = newOrigin.originX
|
|
749
726
|
originY = newOrigin.originY
|
|
750
727
|
absoluteLowerRightHandSide = { x: newOrigin.x, y: newOrigin.y }
|
|
751
|
-
const newestOrigin = drawBottomDwellers(
|
|
752
|
-
object as ContainerLayoutObject,
|
|
753
|
-
originX,
|
|
754
|
-
originY,
|
|
755
|
-
absoluteLowerRightHandSide,
|
|
756
|
-
bottomChildY,
|
|
757
|
-
paperSize,
|
|
758
|
-
doc,
|
|
759
|
-
layout,
|
|
760
|
-
rootPrintBuffer,
|
|
761
|
-
options,
|
|
762
|
-
newContainerChain,
|
|
763
|
-
container,
|
|
764
|
-
context
|
|
765
|
-
)
|
|
728
|
+
const newestOrigin = drawBottomDwellers(object as ContainerLayoutObject, originX, originY, absoluteLowerRightHandSide, bottomChildY, paperSize, doc, layout, rootPrintBuffer, options, newContainerChain, container, context)
|
|
766
729
|
originX = newestOrigin.originX
|
|
767
730
|
originY = newestOrigin.originY
|
|
768
731
|
absoluteLowerRightHandSide = { x: newestOrigin.x, y: newestOrigin.y }
|
|
769
732
|
continue
|
|
770
733
|
}
|
|
771
734
|
}
|
|
772
|
-
const newestOrigin = drawBottomDwellers(
|
|
773
|
-
object as ContainerLayoutObject,
|
|
774
|
-
originX,
|
|
775
|
-
originY,
|
|
776
|
-
absoluteLowerRightHandSide,
|
|
777
|
-
bottomChildY,
|
|
778
|
-
paperSize,
|
|
779
|
-
doc,
|
|
780
|
-
layout,
|
|
781
|
-
rootPrintBuffer,
|
|
782
|
-
options,
|
|
783
|
-
newContainerChain,
|
|
784
|
-
container,
|
|
785
|
-
context
|
|
786
|
-
)
|
|
735
|
+
const newestOrigin = drawBottomDwellers(object as ContainerLayoutObject, originX, originY, absoluteLowerRightHandSide, bottomChildY, paperSize, doc, layout, rootPrintBuffer, options, newContainerChain, container, context)
|
|
787
736
|
originX = newestOrigin.originX
|
|
788
737
|
originY = newestOrigin.originY
|
|
789
738
|
absoluteLowerRightHandSide = { x: newestOrigin.x, y: newestOrigin.y }
|
|
@@ -842,10 +791,12 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
842
791
|
paperSize.height *= 10
|
|
843
792
|
paperSize.footerHeight *= 10
|
|
844
793
|
|
|
845
|
-
// First pass: Measurement mode
|
|
794
|
+
// First pass: Measurement mode — page count without visible output; overlaps must match render pass inputs.
|
|
846
795
|
const measurementContext: RenderContext = {
|
|
847
796
|
mode: 'measurement',
|
|
848
|
-
|
|
797
|
+
currentPageNumber: 1,
|
|
798
|
+
imageAssets,
|
|
799
|
+
defaultFontFamily: layout.defaultFontFamily,
|
|
849
800
|
}
|
|
850
801
|
// Create a minimal jsPDF instance for measurement (needed for some calculations)
|
|
851
802
|
const measurementDoc = new jsPDF({
|
|
@@ -859,41 +810,27 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
859
810
|
drawStaticPartOfPage(measurementDoc, layout, printBuffer, paperSize, options, measurementContext)
|
|
860
811
|
|
|
861
812
|
// Draw containers in measurement mode (same order as render)
|
|
862
|
-
|
|
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
|
|
863
815
|
layout.objects
|
|
864
816
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtStart === true)
|
|
865
817
|
.forEach((object) => {
|
|
866
818
|
const lh = addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
867
|
-
|
|
819
|
+
measuredPrintOnlyAtStartOffset = Math.max(measuredPrintOnlyAtStartOffset, lh.y * 10)
|
|
868
820
|
})
|
|
869
821
|
layout.objects
|
|
870
|
-
.filter(
|
|
871
|
-
(object) =>
|
|
872
|
-
object.type == 'container' &&
|
|
873
|
-
(object as ContainerLayoutObject).printOnlyAtEnd !== true &&
|
|
874
|
-
(object as ContainerLayoutObject).printOnlyAtStart !== true
|
|
875
|
-
)
|
|
822
|
+
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd !== true && (object as ContainerLayoutObject).printOnlyAtStart !== true)
|
|
876
823
|
.forEach((object) => {
|
|
877
|
-
|
|
878
|
-
if (bumpTenths > 0) {
|
|
879
|
-
measurementContext.applyRootStartBumpToThisCall = true
|
|
880
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths
|
|
881
|
-
}
|
|
882
|
-
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))
|
|
883
825
|
})
|
|
884
826
|
layout.objects
|
|
885
827
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true)
|
|
886
828
|
.forEach((object) => {
|
|
887
|
-
|
|
888
|
-
if (bumpTenths > 0) {
|
|
889
|
-
measurementContext.applyRootStartBumpToThisCall = true
|
|
890
|
-
measurementContext.pendingRootStartBumpTenths = bumpTenths
|
|
891
|
-
}
|
|
892
|
-
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))
|
|
893
830
|
})
|
|
894
831
|
|
|
895
832
|
// Get total page count from measurement pass
|
|
896
|
-
const totalPageCount = measurementContext.
|
|
833
|
+
const totalPageCount = measurementContext.currentPageNumber || 1
|
|
897
834
|
|
|
898
835
|
// Second pass: Rendering mode - actual PDF generation with pageCount available
|
|
899
836
|
const doc = new jsPDF({
|
|
@@ -911,42 +848,23 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
911
848
|
}
|
|
912
849
|
drawStaticPartOfPage(doc, layout, printBuffer, paperSize, options, renderContext)
|
|
913
850
|
|
|
914
|
-
let renderTopPrintedStartBottomTenths = 0
|
|
915
851
|
layout.objects
|
|
916
852
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtStart === true)
|
|
917
853
|
.forEach((object) => {
|
|
918
|
-
|
|
919
|
-
renderTopPrintedStartBottomTenths = Math.max(renderTopPrintedStartBottomTenths, lh.y * 10)
|
|
854
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
920
855
|
})
|
|
921
856
|
|
|
922
857
|
// Draw containers in rendering mode (body containers after printOnlyAtStart)
|
|
923
858
|
layout.objects
|
|
924
|
-
.filter(
|
|
925
|
-
(object) =>
|
|
926
|
-
object.type == 'container' &&
|
|
927
|
-
(object as ContainerLayoutObject).printOnlyAtEnd !== true &&
|
|
928
|
-
(object as ContainerLayoutObject).printOnlyAtStart !== true
|
|
929
|
-
)
|
|
859
|
+
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd !== true && (object as ContainerLayoutObject).printOnlyAtStart !== true)
|
|
930
860
|
.forEach((object) => {
|
|
931
|
-
|
|
932
|
-
if (bumpTenths > 0) {
|
|
933
|
-
renderContext.applyRootStartBumpToThisCall = true
|
|
934
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths
|
|
935
|
-
}
|
|
936
|
-
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))
|
|
937
862
|
})
|
|
938
863
|
|
|
939
864
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
940
|
-
const printOnlyAtEndContainers = layout.objects.filter(
|
|
941
|
-
(object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true
|
|
942
|
-
)
|
|
865
|
+
const printOnlyAtEndContainers = layout.objects.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd === true)
|
|
943
866
|
printOnlyAtEndContainers.forEach((object) => {
|
|
944
|
-
|
|
945
|
-
if (bumpTenths > 0) {
|
|
946
|
-
renderContext.applyRootStartBumpToThisCall = true
|
|
947
|
-
renderContext.pendingRootStartBumpTenths = bumpTenths
|
|
948
|
-
}
|
|
949
|
-
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))
|
|
950
868
|
})
|
|
951
869
|
return doc
|
|
952
870
|
}
|
package/test/reports.spec.ts
CHANGED
|
@@ -263,4 +263,72 @@ describe('genPDF', () => {
|
|
|
263
263
|
expect(pdfText).toContain('ROW_0_MARK')
|
|
264
264
|
expect(pdfText).toContain('ROW_35_MARK')
|
|
265
265
|
})
|
|
266
|
+
|
|
267
|
+
it('redraws top-level empty-source body containers on every continuation page beside an overflowing sibling', async () => {
|
|
268
|
+
const chromeText = {
|
|
269
|
+
type: 'text' as const,
|
|
270
|
+
name: 'chrome-label',
|
|
271
|
+
x: 0,
|
|
272
|
+
y: 0,
|
|
273
|
+
width: 300,
|
|
274
|
+
height: 48,
|
|
275
|
+
active: true,
|
|
276
|
+
text: 'CHROME_EACH_PAGE',
|
|
277
|
+
textAlign: 1 as const,
|
|
278
|
+
fontFamily: 'Helvetica',
|
|
279
|
+
fontSize: 28,
|
|
280
|
+
fontStyle: 0,
|
|
281
|
+
}
|
|
282
|
+
const lineField = {
|
|
283
|
+
type: 'field' as const,
|
|
284
|
+
name: 'ln',
|
|
285
|
+
x: 0,
|
|
286
|
+
y: 0,
|
|
287
|
+
width: 800,
|
|
288
|
+
height: 96,
|
|
289
|
+
active: true,
|
|
290
|
+
source: 'line',
|
|
291
|
+
textAlign: 1 as const,
|
|
292
|
+
fontFamily: 'Helvetica',
|
|
293
|
+
fontSize: 36,
|
|
294
|
+
fontStyle: 0,
|
|
295
|
+
}
|
|
296
|
+
const ITEMS = Array.from({ length: 48 }, (_, i) => ({ line: `SKU_${i}` }))
|
|
297
|
+
const layout: Layout = {
|
|
298
|
+
name: 'sibling-chrome',
|
|
299
|
+
paperSize: { width: 210, height: 297, footerHeight: 20 },
|
|
300
|
+
objects: [
|
|
301
|
+
{
|
|
302
|
+
type: 'container',
|
|
303
|
+
name: 'addressBand',
|
|
304
|
+
x: 60,
|
|
305
|
+
y: 440,
|
|
306
|
+
width: 400,
|
|
307
|
+
height: 280,
|
|
308
|
+
active: true,
|
|
309
|
+
source: '',
|
|
310
|
+
children: [chromeText],
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
type: 'container',
|
|
314
|
+
name: 'lines',
|
|
315
|
+
x: 500,
|
|
316
|
+
y: 440,
|
|
317
|
+
width: 1500,
|
|
318
|
+
height: 200,
|
|
319
|
+
active: true,
|
|
320
|
+
source: 'ITEMS',
|
|
321
|
+
repeatContainer: 'vertical' as const,
|
|
322
|
+
children: [lineField],
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const doc = await genPDF(layout, { ITEMS })
|
|
328
|
+
expect(doc.getNumberOfPages()).toBeGreaterThanOrEqual(2)
|
|
329
|
+
const pdfText = Buffer.from(doc.output('arraybuffer')).toString('latin1')
|
|
330
|
+
const chromeMatches = pdfText.match(/\(CHROME_EACH_PAGE\)/g)
|
|
331
|
+
expect(chromeMatches?.length ?? 0).toBeGreaterThanOrEqual(doc.getNumberOfPages())
|
|
332
|
+
expect(pdfText).toContain('SKU_20')
|
|
333
|
+
})
|
|
266
334
|
})
|