@softwear/latestcollectioncore 1.0.178 → 1.0.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/reports.js +38 -14
- package/package.json +1 -1
- package/src/reports.ts +41 -13
- package/test/reports.spec.ts +54 -0
package/dist/reports.js
CHANGED
|
@@ -43,9 +43,21 @@ function getProperty(propertyName, object) {
|
|
|
43
43
|
}
|
|
44
44
|
return property;
|
|
45
45
|
}
|
|
46
|
-
/** Repeat once
|
|
46
|
+
/** Repeat once when the container has no data binding (`source` empty / whitespace-only). */
|
|
47
|
+
function dummyLayoutSource(source) {
|
|
48
|
+
return source === undefined || String(source).trim() === '';
|
|
49
|
+
}
|
|
50
|
+
/** Like repeatOnOverflow: redraw after a page break so nested overflowing content can proceed. */
|
|
51
|
+
function containerRedrawsAfterContinuationPage(child) {
|
|
52
|
+
if (child.type !== 'container')
|
|
53
|
+
return false;
|
|
54
|
+
const c = child;
|
|
55
|
+
if (c.repeatOnOverflow)
|
|
56
|
+
return true;
|
|
57
|
+
return dummyLayoutSource(c.source);
|
|
58
|
+
}
|
|
47
59
|
function containerLoopSource(container, printBuffer) {
|
|
48
|
-
if (
|
|
60
|
+
if (dummyLayoutSource(container.source))
|
|
49
61
|
return [printBuffer];
|
|
50
62
|
return getProperty(container.source, printBuffer);
|
|
51
63
|
}
|
|
@@ -368,6 +380,8 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
368
380
|
}
|
|
369
381
|
}
|
|
370
382
|
function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, containerChain, context) {
|
|
383
|
+
context.pendingRootStartBumpTenths = 0;
|
|
384
|
+
context.applyRootStartBumpToThisCall = false;
|
|
371
385
|
if (context.mode === 'measurement') {
|
|
372
386
|
// Track page count in measurement mode
|
|
373
387
|
if (context.currentPageCount === undefined) {
|
|
@@ -392,7 +406,7 @@ function addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, opti
|
|
|
392
406
|
absoluteLowerRightHandSide.y = originY / 10;
|
|
393
407
|
containerChain.forEach((link) => {
|
|
394
408
|
link.object.children.forEach((child) => {
|
|
395
|
-
if (!child.snapToBottom && (child.type != 'container' || child
|
|
409
|
+
if (!child.snapToBottom && (child.type != 'container' || containerRedrawsAfterContinuationPage(child))) {
|
|
396
410
|
const childLowerRightHandSide = addObjectToPDF(originX, originY, doc, child, link.printBuffer, paperSize, layout, options, rootPrintBuffer, [], context);
|
|
397
411
|
absoluteLowerRightHandSide.x = Math.max(absoluteLowerRightHandSide.x, childLowerRightHandSide.x);
|
|
398
412
|
absoluteLowerRightHandSide.y = Math.max(absoluteLowerRightHandSide.y, childLowerRightHandSide.y);
|
|
@@ -441,9 +455,15 @@ function drawBottomDwellers(object, originX, originY, absoluteLowerRightHandSide
|
|
|
441
455
|
* Use originX,originY as origin to displace the object's own x,y coordinates
|
|
442
456
|
*/
|
|
443
457
|
addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize, layout, options, rootPrintBuffer, containerChain, context) {
|
|
444
|
-
var _a;
|
|
458
|
+
var _a, _b;
|
|
459
|
+
let rootBump = 0;
|
|
460
|
+
if (context.applyRootStartBumpToThisCall) {
|
|
461
|
+
rootBump = (_a = context.pendingRootStartBumpTenths) !== null && _a !== void 0 ? _a : 0;
|
|
462
|
+
context.applyRootStartBumpToThisCall = false;
|
|
463
|
+
context.pendingRootStartBumpTenths = 0;
|
|
464
|
+
}
|
|
445
465
|
const x = (originX + object.x) / 10;
|
|
446
|
-
const y = (originY + object.y) / 10;
|
|
466
|
+
const y = (originY + object.y + rootBump) / 10;
|
|
447
467
|
const width = object.width / 10;
|
|
448
468
|
const height = object.height / 10;
|
|
449
469
|
// Keep track of the lower righthandside of all objects in this container
|
|
@@ -458,7 +478,7 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
|
|
|
458
478
|
let originX = x * 10, originY = y * 10;
|
|
459
479
|
const source = containerLoopSource(object, printBuffer);
|
|
460
480
|
if (source === undefined) {
|
|
461
|
-
(
|
|
481
|
+
(_b = options.onAlert) === null || _b === void 0 ? void 0 : _b.call(options, { header: 'containernotfound', body: object.source, type: 'warning', timeout: 10000 });
|
|
462
482
|
return absoluteLowerRightHandSide;
|
|
463
483
|
}
|
|
464
484
|
const nrContainers = source.length;
|
|
@@ -675,14 +695,16 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
675
695
|
!object.printOnlyAtEnd &&
|
|
676
696
|
!object.printOnlyAtStart)
|
|
677
697
|
.forEach((object) => {
|
|
678
|
-
|
|
679
|
-
|
|
698
|
+
measurementContext.applyRootStartBumpToThisCall = true;
|
|
699
|
+
measurementContext.pendingRootStartBumpTenths = Math.max(0, measurementTopPrintedStartBottomTenths - object.y);
|
|
700
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
680
701
|
});
|
|
681
702
|
layout.objects
|
|
682
703
|
.filter((object) => object.type == 'container' && object.printOnlyAtEnd)
|
|
683
704
|
.forEach((object) => {
|
|
684
|
-
|
|
685
|
-
|
|
705
|
+
measurementContext.applyRootStartBumpToThisCall = true;
|
|
706
|
+
measurementContext.pendingRootStartBumpTenths = Math.max(0, measurementTopPrintedStartBottomTenths - object.y);
|
|
707
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext);
|
|
686
708
|
});
|
|
687
709
|
// Get total page count from measurement pass
|
|
688
710
|
const totalPageCount = measurementContext.currentPageCount || 1;
|
|
@@ -714,14 +736,16 @@ function genPDF(layout, printBuffer, options = {}) {
|
|
|
714
736
|
!object.printOnlyAtEnd &&
|
|
715
737
|
!object.printOnlyAtStart)
|
|
716
738
|
.forEach((object) => {
|
|
717
|
-
|
|
718
|
-
|
|
739
|
+
renderContext.applyRootStartBumpToThisCall = true;
|
|
740
|
+
renderContext.pendingRootStartBumpTenths = Math.max(0, renderTopPrintedStartBottomTenths - object.y);
|
|
741
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
719
742
|
});
|
|
720
743
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
721
744
|
const printOnlyAtEndContainers = layout.objects.filter((object) => object.type == 'container' && object.printOnlyAtEnd);
|
|
722
745
|
printOnlyAtEndContainers.forEach((object) => {
|
|
723
|
-
|
|
724
|
-
|
|
746
|
+
renderContext.applyRootStartBumpToThisCall = true;
|
|
747
|
+
renderContext.pendingRootStartBumpTenths = Math.max(0, renderTopPrintedStartBottomTenths - object.y);
|
|
748
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext);
|
|
725
749
|
});
|
|
726
750
|
return doc;
|
|
727
751
|
});
|
package/package.json
CHANGED
package/src/reports.ts
CHANGED
|
@@ -46,6 +46,10 @@ interface RenderContext {
|
|
|
46
46
|
imageAssets?: Map<string, PdfImageAsset>
|
|
47
47
|
/** Layout default font used when object.fontFamily is undefined */
|
|
48
48
|
defaultFontFamily?: string
|
|
49
|
+
/** Set with {@link pendingRootStartBumpTenths} only for top-level genPDF container draws; consumed on first addObjectToPDF read. */
|
|
50
|
+
applyRootStartBumpToThisCall?: boolean
|
|
51
|
+
/** Vertical pad (tenths-mm) so body roots sit below rendered printOnlyAtStart siblings; use with applyRootStartBumpToThisCall only. */
|
|
52
|
+
pendingRootStartBumpTenths?: number
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
// We have to declare some functions that will be called by other functions but also have to call those other functions
|
|
@@ -92,10 +96,22 @@ function getProperty(propertyName: string, object: any): any {
|
|
|
92
96
|
return property
|
|
93
97
|
}
|
|
94
98
|
|
|
95
|
-
/** Repeat once
|
|
99
|
+
/** Repeat once when the container has no data binding (`source` empty / whitespace-only). */
|
|
100
|
+
function dummyLayoutSource(source?: string): boolean {
|
|
101
|
+
return source === undefined || String(source).trim() === ''
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Like repeatOnOverflow: redraw after a page break so nested overflowing content can proceed. */
|
|
105
|
+
function containerRedrawsAfterContinuationPage(child: LayoutObject): boolean {
|
|
106
|
+
if (child.type !== 'container') return false
|
|
107
|
+
const c = child as ContainerLayoutObject
|
|
108
|
+
if (c.repeatOnOverflow) return true
|
|
109
|
+
return dummyLayoutSource(c.source)
|
|
110
|
+
}
|
|
111
|
+
|
|
96
112
|
function containerLoopSource(container: ContainerLayoutObject, printBuffer: any): any {
|
|
97
|
-
if (
|
|
98
|
-
return getProperty(container.source, printBuffer)
|
|
113
|
+
if (dummyLayoutSource(container.source)) return [printBuffer]
|
|
114
|
+
return getProperty(container.source as string, printBuffer)
|
|
99
115
|
}
|
|
100
116
|
|
|
101
117
|
/** jsPDF font style strings. fontStyle bitmask: 0=normal, 1=bold, 2=italic, 3=bold+italic */
|
|
@@ -433,6 +449,8 @@ function addPage(
|
|
|
433
449
|
containerChain: { object: ContainerLayoutObject; printBuffer: any }[],
|
|
434
450
|
context: RenderContext
|
|
435
451
|
): { originX: number; originY: number; x: number; y: number } {
|
|
452
|
+
context.pendingRootStartBumpTenths = 0
|
|
453
|
+
context.applyRootStartBumpToThisCall = false
|
|
436
454
|
if (context.mode === 'measurement') {
|
|
437
455
|
// Track page count in measurement mode
|
|
438
456
|
if (context.currentPageCount === undefined) {
|
|
@@ -456,7 +474,7 @@ function addPage(
|
|
|
456
474
|
absoluteLowerRightHandSide.y = originY / 10
|
|
457
475
|
containerChain.forEach((link) => {
|
|
458
476
|
link.object.children.forEach((child) => {
|
|
459
|
-
if (!child.snapToBottom && (child.type != 'container' || child
|
|
477
|
+
if (!child.snapToBottom && (child.type != 'container' || containerRedrawsAfterContinuationPage(child))) {
|
|
460
478
|
const childLowerRightHandSide = addObjectToPDF(originX, originY, doc, child, link.printBuffer, paperSize, layout, options, rootPrintBuffer, [], context)
|
|
461
479
|
absoluteLowerRightHandSide.x = Math.max(absoluteLowerRightHandSide.x, childLowerRightHandSide.x)
|
|
462
480
|
absoluteLowerRightHandSide.y = Math.max(absoluteLowerRightHandSide.y, childLowerRightHandSide.y)
|
|
@@ -529,8 +547,14 @@ addObjectToPDF = function (
|
|
|
529
547
|
containerChain: { object: ContainerLayoutObject; printBuffer: any }[],
|
|
530
548
|
context: RenderContext
|
|
531
549
|
): { x: number; y: number } {
|
|
550
|
+
let rootBump = 0
|
|
551
|
+
if (context.applyRootStartBumpToThisCall) {
|
|
552
|
+
rootBump = context.pendingRootStartBumpTenths ?? 0
|
|
553
|
+
context.applyRootStartBumpToThisCall = false
|
|
554
|
+
context.pendingRootStartBumpTenths = 0
|
|
555
|
+
}
|
|
532
556
|
const x = (originX + object.x) / 10
|
|
533
|
-
const y = (originY + object.y) / 10
|
|
557
|
+
const y = (originY + object.y + rootBump) / 10
|
|
534
558
|
const width = object.width / 10
|
|
535
559
|
const height = object.height / 10
|
|
536
560
|
// Keep track of the lower righthandside of all objects in this container
|
|
@@ -801,14 +825,16 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
801
825
|
!(object as ContainerLayoutObject).printOnlyAtStart
|
|
802
826
|
)
|
|
803
827
|
.forEach((object) => {
|
|
804
|
-
|
|
805
|
-
|
|
828
|
+
measurementContext.applyRootStartBumpToThisCall = true
|
|
829
|
+
measurementContext.pendingRootStartBumpTenths = Math.max(0, measurementTopPrintedStartBottomTenths - object.y)
|
|
830
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
806
831
|
})
|
|
807
832
|
layout.objects
|
|
808
833
|
.filter((object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd)
|
|
809
834
|
.forEach((object) => {
|
|
810
|
-
|
|
811
|
-
|
|
835
|
+
measurementContext.applyRootStartBumpToThisCall = true
|
|
836
|
+
measurementContext.pendingRootStartBumpTenths = Math.max(0, measurementTopPrintedStartBottomTenths - object.y)
|
|
837
|
+
addObjectToPDF(0, 0, measurementDoc, object, printBuffer, paperSize, layout, options, printBuffer, [], measurementContext)
|
|
812
838
|
})
|
|
813
839
|
|
|
814
840
|
// Get total page count from measurement pass
|
|
@@ -847,8 +873,9 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
847
873
|
!(object as ContainerLayoutObject).printOnlyAtStart
|
|
848
874
|
)
|
|
849
875
|
.forEach((object) => {
|
|
850
|
-
|
|
851
|
-
|
|
876
|
+
renderContext.applyRootStartBumpToThisCall = true
|
|
877
|
+
renderContext.pendingRootStartBumpTenths = Math.max(0, renderTopPrintedStartBottomTenths - object.y)
|
|
878
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
852
879
|
})
|
|
853
880
|
|
|
854
881
|
// Draw printOnlyAtEnd containers once at the end (at their layout coordinates on current page)
|
|
@@ -856,8 +883,9 @@ export async function genPDF(layout: Layout, printBuffer: any, options: GenPdfOp
|
|
|
856
883
|
(object) => object.type == 'container' && (object as ContainerLayoutObject).printOnlyAtEnd
|
|
857
884
|
)
|
|
858
885
|
printOnlyAtEndContainers.forEach((object) => {
|
|
859
|
-
|
|
860
|
-
|
|
886
|
+
renderContext.applyRootStartBumpToThisCall = true
|
|
887
|
+
renderContext.pendingRootStartBumpTenths = Math.max(0, renderTopPrintedStartBottomTenths - object.y)
|
|
888
|
+
addObjectToPDF(0, 0, doc, object, printBuffer, paperSize, layout, options, printBuffer, [], renderContext)
|
|
861
889
|
})
|
|
862
890
|
return doc
|
|
863
891
|
}
|
package/test/reports.spec.ts
CHANGED
|
@@ -209,4 +209,58 @@ describe('genPDF', () => {
|
|
|
209
209
|
expect(iB).toBeGreaterThanOrEqual(0)
|
|
210
210
|
expect(iH).toBeLessThan(iB)
|
|
211
211
|
})
|
|
212
|
+
|
|
213
|
+
it('redraws empty-source wrapper so inner vertical repeat spans multiple pages', async () => {
|
|
214
|
+
const rowField = {
|
|
215
|
+
type: 'field' as const,
|
|
216
|
+
name: 'ln',
|
|
217
|
+
x: 0,
|
|
218
|
+
y: 0,
|
|
219
|
+
width: 1600,
|
|
220
|
+
height: 80,
|
|
221
|
+
active: true,
|
|
222
|
+
source: 'line',
|
|
223
|
+
textAlign: 1 as const,
|
|
224
|
+
fontFamily: 'Helvetica',
|
|
225
|
+
fontSize: 36,
|
|
226
|
+
fontStyle: 0,
|
|
227
|
+
}
|
|
228
|
+
const ROWS = Array.from({ length: 40 }, (_, i) => ({ line: `ROW_${i}_MARK` }))
|
|
229
|
+
const layout: Layout = {
|
|
230
|
+
name: 'wrapper-overflow',
|
|
231
|
+
paperSize: { width: 210, height: 297, footerHeight: 20 },
|
|
232
|
+
objects: [
|
|
233
|
+
{
|
|
234
|
+
type: 'container',
|
|
235
|
+
name: 'wrap',
|
|
236
|
+
x: 50,
|
|
237
|
+
y: 100,
|
|
238
|
+
width: 1900,
|
|
239
|
+
height: 2800,
|
|
240
|
+
active: true,
|
|
241
|
+
source: '',
|
|
242
|
+
children: [
|
|
243
|
+
{
|
|
244
|
+
type: 'container',
|
|
245
|
+
name: 'rows',
|
|
246
|
+
x: 0,
|
|
247
|
+
y: 0,
|
|
248
|
+
width: 1800,
|
|
249
|
+
height: 120,
|
|
250
|
+
active: true,
|
|
251
|
+
source: 'ROWS',
|
|
252
|
+
repeatContainer: 'vertical' as const,
|
|
253
|
+
children: [rowField],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const doc = await genPDF(layout, { ROWS })
|
|
261
|
+
expect(doc.getNumberOfPages()).toBeGreaterThanOrEqual(2)
|
|
262
|
+
const pdfText = Buffer.from(doc.output('arraybuffer')).toString('latin1')
|
|
263
|
+
expect(pdfText).toContain('ROW_0_MARK')
|
|
264
|
+
expect(pdfText).toContain('ROW_35_MARK')
|
|
265
|
+
})
|
|
212
266
|
})
|