@jsonpdf/renderer 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/anchors.d.ts +13 -0
- package/dist/anchors.d.ts.map +1 -0
- package/dist/anchors.js +37 -0
- package/dist/anchors.js.map +1 -0
- package/dist/band-expander.d.ts +25 -0
- package/dist/band-expander.d.ts.map +1 -0
- package/dist/band-expander.js +193 -0
- package/dist/band-expander.js.map +1 -0
- package/dist/bookmarks.d.ts +22 -0
- package/dist/bookmarks.d.ts.map +1 -0
- package/dist/bookmarks.js +78 -0
- package/dist/bookmarks.js.map +1 -0
- package/dist/columns.d.ts +18 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +31 -0
- package/dist/columns.js.map +1 -0
- package/dist/context.d.ts +8 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +38 -0
- package/dist/context.js.map +1 -0
- package/dist/coordinate.d.ts +14 -0
- package/dist/coordinate.d.ts.map +1 -0
- package/dist/coordinate.js +16 -0
- package/dist/coordinate.js.map +1 -0
- package/dist/data.d.ts +18 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +56 -0
- package/dist/data.js.map +1 -0
- package/dist/expression.d.ts +13 -0
- package/dist/expression.d.ts.map +1 -0
- package/dist/expression.js +90 -0
- package/dist/expression.js.map +1 -0
- package/dist/font-loader.d.ts +8 -0
- package/dist/font-loader.d.ts.map +1 -0
- package/dist/font-loader.js +29 -0
- package/dist/font-loader.js.map +1 -0
- package/dist/fonts.d.ts +19 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +124 -0
- package/dist/fonts.js.map +1 -0
- package/dist/footnotes.d.ts +34 -0
- package/dist/footnotes.d.ts.map +1 -0
- package/dist/footnotes.js +103 -0
- package/dist/footnotes.js.map +1 -0
- package/dist/gradient.d.ts +19 -0
- package/dist/gradient.d.ts.map +1 -0
- package/dist/gradient.js +176 -0
- package/dist/gradient.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +54 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +680 -0
- package/dist/layout.js.map +1 -0
- package/dist/renderer.d.ts +19 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +570 -0
- package/dist/renderer.js.map +1 -0
- package/dist/style-resolver.d.ts +15 -0
- package/dist/style-resolver.d.ts.map +1 -0
- package/dist/style-resolver.js +39 -0
- package/dist/style-resolver.js.map +1 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JsonPDF
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @jsonpdf/renderer
|
|
2
|
+
|
|
3
|
+
PDF generation pipeline for jsonpdf — takes a template and data, produces a PDF.
|
|
4
|
+
|
|
5
|
+
## Pipeline
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Template + Data
|
|
9
|
+
→ Validate (schema check)
|
|
10
|
+
→ Resolve (LiquidJS expressions → concrete values)
|
|
11
|
+
→ Measure (compute element sizes via plugins)
|
|
12
|
+
→ Layout (page breaks, columns, band placement)
|
|
13
|
+
→ Render (draw to PDF via pdf-lib)
|
|
14
|
+
→ PDF bytes
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The renderer uses **two-pass rendering** to support `_totalPages` — the first pass computes the page count, then the second pass renders with the final value available.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- LiquidJS expression binding with dot-path data resolution
|
|
22
|
+
- Conditional bands (show/hide based on expressions)
|
|
23
|
+
- Data-driven band iteration (`dataSource` property)
|
|
24
|
+
- Multi-section layouts with independent page configurations
|
|
25
|
+
- Multi-column layouts
|
|
26
|
+
- Footnotes
|
|
27
|
+
- PDF bookmarks/outlines
|
|
28
|
+
- Anchor links
|
|
29
|
+
- Gradient fills
|
|
30
|
+
- Font embedding with weight/style variants
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { renderPdf } from '@jsonpdf/renderer';
|
|
36
|
+
|
|
37
|
+
const result = await renderPdf(template, data, {
|
|
38
|
+
fonts: fontMap,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// result.pdf — Uint8Array of PDF bytes
|
|
42
|
+
// result.pages — number of pages rendered
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Exports
|
|
46
|
+
|
|
47
|
+
| Category | Exports |
|
|
48
|
+
| ----------- | ------------------------------------------------------------- |
|
|
49
|
+
| Main | `renderPdf`, `RenderOptions`, `RenderResult` |
|
|
50
|
+
| Expressions | `createExpressionEngine`, `ExpressionEngine` |
|
|
51
|
+
| Data | `validateData`, `resolveDotPath`, `buildScope` |
|
|
52
|
+
| Layout | `mergePageConfig`, `LayoutBand`, `LayoutPage`, `LayoutResult` |
|
|
53
|
+
| Bands | `BandInstance`, `ExpandedSection` |
|
|
54
|
+
| Fonts | `embedFonts`, `collectFontSpecs`, `mapWeight`, `FontSpec` |
|
|
55
|
+
| Bookmarks | `collectAnchors`, `buildPdfOutline`, `BookmarkEntry` |
|
|
56
|
+
| Columns | `computeColumnLayout`, `ColumnLayout` |
|
|
57
|
+
| Platform | `initBrowser` (re-exported from `@jsonpdf/plugins`) |
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LayoutResult } from './layout.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collect all anchor IDs from a layout result.
|
|
4
|
+
* Returns a map from anchor ID to 1-based page number.
|
|
5
|
+
*
|
|
6
|
+
* Scans both band-level anchors (`band.anchor`) and element-level
|
|
7
|
+
* anchors (`element.anchor`). If the same anchor ID appears multiple
|
|
8
|
+
* times, the first occurrence wins.
|
|
9
|
+
*/
|
|
10
|
+
export declare function collectAnchors(layout: LayoutResult, options?: {
|
|
11
|
+
warnOnDuplicates?: boolean;
|
|
12
|
+
}): Map<string, number>;
|
|
13
|
+
//# sourceMappingURL=anchors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../src/anchors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,GACvC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiCrB"}
|
package/dist/anchors.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collect all anchor IDs from a layout result.
|
|
3
|
+
* Returns a map from anchor ID to 1-based page number.
|
|
4
|
+
*
|
|
5
|
+
* Scans both band-level anchors (`band.anchor`) and element-level
|
|
6
|
+
* anchors (`element.anchor`). If the same anchor ID appears multiple
|
|
7
|
+
* times, the first occurrence wins.
|
|
8
|
+
*/
|
|
9
|
+
export function collectAnchors(layout, options) {
|
|
10
|
+
const warn = options?.warnOnDuplicates ?? false;
|
|
11
|
+
const anchors = new Map();
|
|
12
|
+
for (const page of layout.pages) {
|
|
13
|
+
const pageNumber = page.pageIndex + 1;
|
|
14
|
+
for (const layoutBand of page.bands) {
|
|
15
|
+
if (layoutBand.band.anchor) {
|
|
16
|
+
if (!anchors.has(layoutBand.band.anchor)) {
|
|
17
|
+
anchors.set(layoutBand.band.anchor, pageNumber);
|
|
18
|
+
}
|
|
19
|
+
else if (warn) {
|
|
20
|
+
console.warn(`Duplicate anchor "${layoutBand.band.anchor}" on page ${String(pageNumber)}; first occurrence on page ${String(anchors.get(layoutBand.band.anchor))} used`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const element of layoutBand.band.elements) {
|
|
24
|
+
if (element.anchor) {
|
|
25
|
+
if (!anchors.has(element.anchor)) {
|
|
26
|
+
anchors.set(element.anchor, pageNumber);
|
|
27
|
+
}
|
|
28
|
+
else if (warn) {
|
|
29
|
+
console.warn(`Duplicate anchor "${element.anchor}" on page ${String(pageNumber)}; first occurrence on page ${String(anchors.get(element.anchor))} used`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return anchors;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=anchors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.js","sourceRoot":"","sources":["../src/anchors.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAoB,EACpB,OAAwC;IAExC,MAAM,IAAI,GAAG,OAAO,EAAE,gBAAgB,IAAI,KAAK,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAEtC,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAClD,CAAC;qBAAM,IAAI,IAAI,EAAE,CAAC;oBAChB,OAAO,CAAC,IAAI,CACV,qBAAqB,UAAU,CAAC,IAAI,CAAC,MAAM,aAAa,MAAM,CAAC,UAAU,CAAC,8BAA8B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAC3J,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC/C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;wBACjC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;oBAC1C,CAAC;yBAAM,IAAI,IAAI,EAAE,CAAC;wBAChB,OAAO,CAAC,IAAI,CACV,qBAAqB,OAAO,CAAC,MAAM,aAAa,MAAM,CAAC,UAAU,CAAC,8BAA8B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAC3I,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Band, Section } from '@jsonpdf/core';
|
|
2
|
+
import type { ExpressionEngine } from './expression.js';
|
|
3
|
+
/** A band instance with its associated Liquid scope. */
|
|
4
|
+
export interface BandInstance {
|
|
5
|
+
band: Band;
|
|
6
|
+
scope: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
/** Bands separated by their structural role within a section. */
|
|
9
|
+
export interface ExpandedSection {
|
|
10
|
+
pageHeaderBands: Band[];
|
|
11
|
+
pageFooterBands: Band[];
|
|
12
|
+
lastPageFooterBands: Band[];
|
|
13
|
+
columnHeaderBands: Band[];
|
|
14
|
+
columnFooterBands: Band[];
|
|
15
|
+
backgroundBands: Band[];
|
|
16
|
+
contentBands: BandInstance[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Expand a section's bands into structural roles and ordered content instances.
|
|
20
|
+
*
|
|
21
|
+
* Content band ordering: title → [groupHeader → detail items → groupFooter] → body → summary
|
|
22
|
+
* NoData bands are included only when detail bands exist but produce no items.
|
|
23
|
+
*/
|
|
24
|
+
export declare function expandBands(section: Section, data: Record<string, unknown>, engine: ExpressionEngine, totalPages: number): Promise<ExpandedSection>;
|
|
25
|
+
//# sourceMappingURL=band-expander.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"band-expander.d.ts","sourceRoot":"","sources":["../src/band-expander.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,IAAI,EAAE,CAAC;IACxB,eAAe,EAAE,IAAI,EAAE,CAAC;IACxB,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAC5B,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC1B,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC1B,eAAe,EAAE,IAAI,EAAE,CAAC;IACxB,YAAY,EAAE,YAAY,EAAE,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAoK1B"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { resolveDotPath, buildScope } from './data.js';
|
|
2
|
+
/**
|
|
3
|
+
* Expand a section's bands into structural roles and ordered content instances.
|
|
4
|
+
*
|
|
5
|
+
* Content band ordering: title → [groupHeader → detail items → groupFooter] → body → summary
|
|
6
|
+
* NoData bands are included only when detail bands exist but produce no items.
|
|
7
|
+
*/
|
|
8
|
+
export async function expandBands(section, data, engine, totalPages) {
|
|
9
|
+
const result = {
|
|
10
|
+
pageHeaderBands: [],
|
|
11
|
+
pageFooterBands: [],
|
|
12
|
+
lastPageFooterBands: [],
|
|
13
|
+
columnHeaderBands: [],
|
|
14
|
+
columnFooterBands: [],
|
|
15
|
+
backgroundBands: [],
|
|
16
|
+
contentBands: [],
|
|
17
|
+
};
|
|
18
|
+
// Separate structural bands
|
|
19
|
+
const titleBands = [];
|
|
20
|
+
const detailBands = [];
|
|
21
|
+
const bodyBands = [];
|
|
22
|
+
const summaryBands = [];
|
|
23
|
+
const noDataBands = [];
|
|
24
|
+
const groupHeaderBands = [];
|
|
25
|
+
const groupFooterBands = [];
|
|
26
|
+
for (const band of section.bands) {
|
|
27
|
+
switch (band.type) {
|
|
28
|
+
case 'pageHeader':
|
|
29
|
+
result.pageHeaderBands.push(band);
|
|
30
|
+
break;
|
|
31
|
+
case 'pageFooter':
|
|
32
|
+
result.pageFooterBands.push(band);
|
|
33
|
+
break;
|
|
34
|
+
case 'lastPageFooter':
|
|
35
|
+
result.lastPageFooterBands.push(band);
|
|
36
|
+
break;
|
|
37
|
+
case 'columnHeader':
|
|
38
|
+
result.columnHeaderBands.push(band);
|
|
39
|
+
break;
|
|
40
|
+
case 'columnFooter':
|
|
41
|
+
result.columnFooterBands.push(band);
|
|
42
|
+
break;
|
|
43
|
+
case 'background':
|
|
44
|
+
result.backgroundBands.push(band);
|
|
45
|
+
break;
|
|
46
|
+
case 'title':
|
|
47
|
+
titleBands.push(band);
|
|
48
|
+
break;
|
|
49
|
+
case 'detail':
|
|
50
|
+
detailBands.push(band);
|
|
51
|
+
break;
|
|
52
|
+
case 'body':
|
|
53
|
+
bodyBands.push(band);
|
|
54
|
+
break;
|
|
55
|
+
case 'summary':
|
|
56
|
+
summaryBands.push(band);
|
|
57
|
+
break;
|
|
58
|
+
case 'noData':
|
|
59
|
+
noDataBands.push(band);
|
|
60
|
+
break;
|
|
61
|
+
case 'groupHeader':
|
|
62
|
+
groupHeaderBands.push(band);
|
|
63
|
+
break;
|
|
64
|
+
case 'groupFooter':
|
|
65
|
+
groupFooterBands.push(band);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const baseScope = buildScope(data, 0, totalPages);
|
|
70
|
+
// Title bands (first in content order)
|
|
71
|
+
for (const band of titleBands) {
|
|
72
|
+
if (await shouldInclude(band, baseScope, engine)) {
|
|
73
|
+
result.contentBands.push({ band, scope: baseScope });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Detail bands with iteration
|
|
77
|
+
let hasDetailItems = false;
|
|
78
|
+
for (const band of detailBands) {
|
|
79
|
+
if (!band.dataSource) {
|
|
80
|
+
throw new Error(`Detail band "${band.id}" must have a dataSource property`);
|
|
81
|
+
}
|
|
82
|
+
const sourceArray = resolveDotPath(data, band.dataSource);
|
|
83
|
+
if (!Array.isArray(sourceArray) || sourceArray.length === 0) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
hasDetailItems = true;
|
|
87
|
+
const itemName = band.itemName ?? 'item';
|
|
88
|
+
if (band.groupBy) {
|
|
89
|
+
// Group the array
|
|
90
|
+
const groups = groupByKey(sourceArray, band.groupBy);
|
|
91
|
+
for (const group of groups) {
|
|
92
|
+
const groupScope = {
|
|
93
|
+
...baseScope,
|
|
94
|
+
_groupKey: group.key,
|
|
95
|
+
_groupItems: group.items,
|
|
96
|
+
};
|
|
97
|
+
// Group headers
|
|
98
|
+
for (const gh of groupHeaderBands) {
|
|
99
|
+
if (await shouldInclude(gh, groupScope, engine)) {
|
|
100
|
+
result.contentBands.push({ band: gh, scope: groupScope });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Detail items within group
|
|
104
|
+
for (let i = 0; i < group.items.length; i++) {
|
|
105
|
+
const itemScope = buildScope(data, 0, totalPages, {
|
|
106
|
+
item: group.items[i],
|
|
107
|
+
itemName,
|
|
108
|
+
index: i,
|
|
109
|
+
});
|
|
110
|
+
itemScope['_groupKey'] = group.key;
|
|
111
|
+
if (await shouldInclude(band, itemScope, engine)) {
|
|
112
|
+
result.contentBands.push({ band, scope: itemScope });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Group footers
|
|
116
|
+
for (const gf of groupFooterBands) {
|
|
117
|
+
if (await shouldInclude(gf, groupScope, engine)) {
|
|
118
|
+
result.contentBands.push({ band: gf, scope: groupScope });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Simple iteration
|
|
125
|
+
for (let i = 0; i < sourceArray.length; i++) {
|
|
126
|
+
const itemScope = buildScope(data, 0, totalPages, {
|
|
127
|
+
item: sourceArray[i],
|
|
128
|
+
itemName,
|
|
129
|
+
index: i,
|
|
130
|
+
});
|
|
131
|
+
if (await shouldInclude(band, itemScope, engine)) {
|
|
132
|
+
result.contentBands.push({ band, scope: itemScope });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// NoData bands (only when no detail items were produced)
|
|
138
|
+
if (!hasDetailItems && detailBands.length > 0 && noDataBands.length > 0) {
|
|
139
|
+
for (const band of noDataBands) {
|
|
140
|
+
if (await shouldInclude(band, baseScope, engine)) {
|
|
141
|
+
result.contentBands.push({ band, scope: baseScope });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Body bands
|
|
146
|
+
for (const band of bodyBands) {
|
|
147
|
+
if (await shouldInclude(band, baseScope, engine)) {
|
|
148
|
+
result.contentBands.push({ band, scope: baseScope });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Summary bands (last in content order)
|
|
152
|
+
for (const band of summaryBands) {
|
|
153
|
+
if (await shouldInclude(band, baseScope, engine)) {
|
|
154
|
+
result.contentBands.push({ band, scope: baseScope });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
/** Check if a band should be included based on its condition. */
|
|
160
|
+
async function shouldInclude(band, scope, engine) {
|
|
161
|
+
if (!band.condition)
|
|
162
|
+
return true;
|
|
163
|
+
return engine.evaluate(band.condition, scope);
|
|
164
|
+
}
|
|
165
|
+
/** Group an array by a property path. */
|
|
166
|
+
function groupByKey(array, keyPath) {
|
|
167
|
+
const groupMap = new Map();
|
|
168
|
+
const groupOrder = [];
|
|
169
|
+
for (const item of array) {
|
|
170
|
+
let key;
|
|
171
|
+
if (item !== null && typeof item === 'object') {
|
|
172
|
+
const val = item[keyPath];
|
|
173
|
+
if (typeof val === 'string')
|
|
174
|
+
key = val;
|
|
175
|
+
else if (typeof val === 'number' || typeof val === 'boolean')
|
|
176
|
+
key = String(val);
|
|
177
|
+
else
|
|
178
|
+
key = '';
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
key = '';
|
|
182
|
+
}
|
|
183
|
+
if (!groupMap.has(key)) {
|
|
184
|
+
groupMap.set(key, []);
|
|
185
|
+
groupOrder.push(key);
|
|
186
|
+
}
|
|
187
|
+
const items = groupMap.get(key);
|
|
188
|
+
if (items)
|
|
189
|
+
items.push(item);
|
|
190
|
+
}
|
|
191
|
+
return groupOrder.map((key) => ({ key, items: groupMap.get(key) ?? [] }));
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=band-expander.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"band-expander.js","sourceRoot":"","sources":["../src/band-expander.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PDFDocument, PDFPage } from 'pdf-lib';
|
|
2
|
+
export interface BookmarkEntry {
|
|
3
|
+
/** Display title in the PDF outline panel. */
|
|
4
|
+
title: string;
|
|
5
|
+
/** The PDF page this bookmark points to. */
|
|
6
|
+
page: PDFPage;
|
|
7
|
+
/** Y position in pdf-lib coordinates (from bottom of page). */
|
|
8
|
+
top: number;
|
|
9
|
+
/** X position in pdf-lib coordinates. */
|
|
10
|
+
left: number;
|
|
11
|
+
/** Nesting level: 0 = section, 1 = band. */
|
|
12
|
+
level: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build a PDF outline (bookmarks panel) from collected entries.
|
|
16
|
+
*
|
|
17
|
+
* Level 0 entries become top-level items. Level 1+ entries become
|
|
18
|
+
* children of the most recent lower-level entry. Items at the same
|
|
19
|
+
* level are siblings.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildPdfOutline(doc: PDFDocument, entries: BookmarkEntry[]): void;
|
|
22
|
+
//# sourceMappingURL=bookmarks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookmarks.d.ts","sourceRoot":"","sources":["../src/bookmarks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAsB,MAAM,SAAS,CAAC;AAGxE,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;CACf;AASD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI,CA8ChF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { PDFName, PDFString, PDFNumber, PDFArray, PDFNull } from 'pdf-lib';
|
|
2
|
+
/**
|
|
3
|
+
* Build a PDF outline (bookmarks panel) from collected entries.
|
|
4
|
+
*
|
|
5
|
+
* Level 0 entries become top-level items. Level 1+ entries become
|
|
6
|
+
* children of the most recent lower-level entry. Items at the same
|
|
7
|
+
* level are siblings.
|
|
8
|
+
*/
|
|
9
|
+
export function buildPdfOutline(doc, entries) {
|
|
10
|
+
if (entries.length === 0)
|
|
11
|
+
return;
|
|
12
|
+
const context = doc.context;
|
|
13
|
+
// Build hierarchy using a stack
|
|
14
|
+
const rootItems = [];
|
|
15
|
+
const stack = [];
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
const dest = createDestination(context, entry);
|
|
18
|
+
const dict = context.obj({
|
|
19
|
+
Title: PDFString.of(entry.title),
|
|
20
|
+
Dest: dest,
|
|
21
|
+
});
|
|
22
|
+
const ref = context.register(dict);
|
|
23
|
+
const item = { ref, dict, entry, children: [] };
|
|
24
|
+
// Pop stack until we find a parent at a lower level
|
|
25
|
+
while (stack.length > 0 && stack[stack.length - 1].entry.level >= entry.level) {
|
|
26
|
+
stack.pop();
|
|
27
|
+
}
|
|
28
|
+
if (stack.length > 0) {
|
|
29
|
+
stack[stack.length - 1].children.push(item);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
rootItems.push(item);
|
|
33
|
+
}
|
|
34
|
+
stack.push(item);
|
|
35
|
+
}
|
|
36
|
+
// Create outline root dictionary
|
|
37
|
+
const outlineDict = context.obj({ Type: 'Outlines' });
|
|
38
|
+
const outlineRef = context.register(outlineDict);
|
|
39
|
+
// Recursively link items with Parent/Prev/Next/First/Last/Count
|
|
40
|
+
const totalCount = linkItems(rootItems, outlineRef);
|
|
41
|
+
outlineDict.set(PDFName.of('First'), rootItems[0].ref);
|
|
42
|
+
outlineDict.set(PDFName.of('Last'), rootItems[rootItems.length - 1].ref);
|
|
43
|
+
outlineDict.set(PDFName.of('Count'), PDFNumber.of(totalCount));
|
|
44
|
+
// Set the outline on the document catalog
|
|
45
|
+
doc.catalog.set(PDFName.of('Outlines'), outlineRef);
|
|
46
|
+
}
|
|
47
|
+
function linkItems(items, parentRef) {
|
|
48
|
+
let totalCount = 0;
|
|
49
|
+
for (let i = 0; i < items.length; i++) {
|
|
50
|
+
const item = items[i];
|
|
51
|
+
item.dict.set(PDFName.of('Parent'), parentRef);
|
|
52
|
+
if (i > 0) {
|
|
53
|
+
item.dict.set(PDFName.of('Prev'), items[i - 1].ref);
|
|
54
|
+
}
|
|
55
|
+
if (i < items.length - 1) {
|
|
56
|
+
item.dict.set(PDFName.of('Next'), items[i + 1].ref);
|
|
57
|
+
}
|
|
58
|
+
totalCount++;
|
|
59
|
+
if (item.children.length > 0) {
|
|
60
|
+
const childCount = linkItems(item.children, item.ref);
|
|
61
|
+
item.dict.set(PDFName.of('First'), item.children[0].ref);
|
|
62
|
+
item.dict.set(PDFName.of('Last'), item.children[item.children.length - 1].ref);
|
|
63
|
+
item.dict.set(PDFName.of('Count'), PDFNumber.of(childCount));
|
|
64
|
+
totalCount += childCount;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return totalCount;
|
|
68
|
+
}
|
|
69
|
+
function createDestination(context, entry) {
|
|
70
|
+
const arr = PDFArray.withContext(context);
|
|
71
|
+
arr.push(entry.page.ref);
|
|
72
|
+
arr.push(PDFName.of('XYZ'));
|
|
73
|
+
arr.push(PDFNumber.of(entry.left));
|
|
74
|
+
arr.push(PDFNumber.of(entry.top));
|
|
75
|
+
arr.push(PDFNull);
|
|
76
|
+
return arr;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=bookmarks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bookmarks.js","sourceRoot":"","sources":["../src/bookmarks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Computed column geometry for multi-column layout. */
|
|
2
|
+
export interface ColumnLayout {
|
|
3
|
+
/** Width of each column in points. */
|
|
4
|
+
widths: number[];
|
|
5
|
+
/** X-offset from the left margin for each column. */
|
|
6
|
+
offsets: number[];
|
|
7
|
+
/** Gap between columns. */
|
|
8
|
+
gap: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Compute column layout geometry.
|
|
12
|
+
*
|
|
13
|
+
* Equal columns: `width = (contentWidth - (columns - 1) * gap) / columns`
|
|
14
|
+
* Asymmetric: `columnWidths` are ratios normalized to fill available space.
|
|
15
|
+
* If `columnWidths.length` doesn't match `columns`, falls back to equal.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeColumnLayout(contentWidth: number, columns: number, columnGap: number, columnWidths?: number[]): ColumnLayout;
|
|
18
|
+
//# sourceMappingURL=columns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columns.d.ts","sourceRoot":"","sources":["../src/columns.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,YAAY,CAyBd"}
|
package/dist/columns.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute column layout geometry.
|
|
3
|
+
*
|
|
4
|
+
* Equal columns: `width = (contentWidth - (columns - 1) * gap) / columns`
|
|
5
|
+
* Asymmetric: `columnWidths` are ratios normalized to fill available space.
|
|
6
|
+
* If `columnWidths.length` doesn't match `columns`, falls back to equal.
|
|
7
|
+
*/
|
|
8
|
+
export function computeColumnLayout(contentWidth, columns, columnGap, columnWidths) {
|
|
9
|
+
if (columns <= 1) {
|
|
10
|
+
return { widths: [contentWidth], offsets: [0], gap: 0 };
|
|
11
|
+
}
|
|
12
|
+
const totalGap = (columns - 1) * columnGap;
|
|
13
|
+
const availableWidth = Math.max(0, contentWidth - totalGap);
|
|
14
|
+
let widths;
|
|
15
|
+
if (columnWidths && columnWidths.length === columns) {
|
|
16
|
+
const totalRatio = columnWidths.reduce((sum, r) => sum + r, 0);
|
|
17
|
+
widths = columnWidths.map((r) => (r / totalRatio) * availableWidth);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
const w = availableWidth / columns;
|
|
21
|
+
widths = Array.from({ length: columns }, () => w);
|
|
22
|
+
}
|
|
23
|
+
const offsets = [];
|
|
24
|
+
let x = 0;
|
|
25
|
+
for (let i = 0; i < columns; i++) {
|
|
26
|
+
offsets.push(x);
|
|
27
|
+
x += widths[i] + columnGap;
|
|
28
|
+
}
|
|
29
|
+
return { widths, offsets, gap: columnGap };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=columns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columns.js","sourceRoot":"","sources":["../src/columns.ts"],"names":[],"mappings":"AAUA;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAoB,EACpB,OAAe,EACf,SAAiB,EACjB,YAAuB;IAEvB,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC,CAAC;IAE5D,IAAI,MAAgB,CAAC;IACrB,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,cAAc,CAAC,CAAC;IACtE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,cAAc,GAAG,OAAO,CAAC;QACnC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PDFDocument, PDFPage } from 'pdf-lib';
|
|
2
|
+
import type { MeasureContext, RenderContext, FontMap, ImageCache } from '@jsonpdf/plugins';
|
|
3
|
+
import type { Element, Style } from '@jsonpdf/core';
|
|
4
|
+
/** Create a MeasureContext for an element. */
|
|
5
|
+
export declare function createMeasureContext(element: Element, fonts: FontMap, styles: Record<string, Style>, defaultStyle: Style, pdfDoc: PDFDocument, imageCache: ImageCache): MeasureContext;
|
|
6
|
+
/** Create a RenderContext for an element. */
|
|
7
|
+
export declare function createRenderContext(element: Element, fonts: FontMap, styles: Record<string, Style>, defaultStyle: Style, page: PDFPage, bandOffsetY: number, pageHeight: number, marginTop: number, marginLeft: number, pdfDoc: PDFDocument, imageCache: ImageCache, measuredHeight?: number): RenderContext;
|
|
8
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC3F,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAIpD,8CAA8C;AAC9C,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC7B,YAAY,EAAE,KAAK,EACnB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,GACrB,cAAc,CAYhB;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC7B,YAAY,EAAE,KAAK,EACnB,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB,aAAa,CAyBf"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { resolveElementStyle, resolveNamedStyle, normalizePadding } from './style-resolver.js';
|
|
2
|
+
import { templateToPdf } from './coordinate.js';
|
|
3
|
+
/** Create a MeasureContext for an element. */
|
|
4
|
+
export function createMeasureContext(element, fonts, styles, defaultStyle, pdfDoc, imageCache) {
|
|
5
|
+
const elementStyle = resolveElementStyle(element, styles, defaultStyle);
|
|
6
|
+
const padding = normalizePadding(elementStyle.padding);
|
|
7
|
+
return {
|
|
8
|
+
fonts,
|
|
9
|
+
availableWidth: element.width - padding.left - padding.right,
|
|
10
|
+
availableHeight: element.height - padding.top - padding.bottom,
|
|
11
|
+
resolveStyle: (name) => resolveNamedStyle(name, styles, defaultStyle),
|
|
12
|
+
elementStyle,
|
|
13
|
+
pdfDoc,
|
|
14
|
+
imageCache,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Create a RenderContext for an element. */
|
|
18
|
+
export function createRenderContext(element, fonts, styles, defaultStyle, page, bandOffsetY, pageHeight, marginTop, marginLeft, pdfDoc, imageCache, measuredHeight) {
|
|
19
|
+
const elementStyle = resolveElementStyle(element, styles, defaultStyle);
|
|
20
|
+
const padding = normalizePadding(elementStyle.padding);
|
|
21
|
+
const { x, y } = templateToPdf(element.x, bandOffsetY + element.y, pageHeight, marginTop, marginLeft);
|
|
22
|
+
const height = measuredHeight ?? element.height;
|
|
23
|
+
return {
|
|
24
|
+
fonts,
|
|
25
|
+
availableWidth: element.width - padding.left - padding.right,
|
|
26
|
+
availableHeight: height - padding.top - padding.bottom,
|
|
27
|
+
resolveStyle: (name) => resolveNamedStyle(name, styles, defaultStyle),
|
|
28
|
+
elementStyle,
|
|
29
|
+
pdfDoc,
|
|
30
|
+
imageCache,
|
|
31
|
+
page,
|
|
32
|
+
x: x + padding.left,
|
|
33
|
+
y: y - padding.top,
|
|
34
|
+
width: element.width - padding.left - padding.right,
|
|
35
|
+
height: height - padding.top - padding.bottom,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,8CAA8C;AAC9C,MAAM,UAAU,oBAAoB,CAClC,OAAgB,EAChB,KAAc,EACd,MAA6B,EAC7B,YAAmB,EACnB,MAAmB,EACnB,UAAsB;IAEtB,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO;QACL,KAAK;QACL,cAAc,EAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK;QAC5D,eAAe,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM;QAC9D,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC;QAC7E,YAAY;QACZ,MAAM;QACN,UAAU;KACX,CAAC;AACJ,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,KAAc,EACd,MAA6B,EAC7B,YAAmB,EACnB,IAAa,EACb,WAAmB,EACnB,UAAkB,EAClB,SAAiB,EACjB,UAAkB,EAClB,MAAmB,EACnB,UAAsB,EACtB,cAAuB;IAEvB,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,aAAa,CAC5B,OAAO,CAAC,CAAC,EACT,WAAW,GAAG,OAAO,CAAC,CAAC,EACvB,UAAU,EACV,SAAS,EACT,UAAU,CACX,CAAC;IACF,MAAM,MAAM,GAAG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,OAAO;QACL,KAAK;QACL,cAAc,EAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK;QAC5D,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM;QACtD,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC;QAC7E,YAAY;QACZ,MAAM;QACN,UAAU;QACV,IAAI;QACJ,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI;QACnB,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,GAAG;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK;QACnD,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM;KAC9C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate from template coordinates (top-left origin) to pdf-lib
|
|
3
|
+
* coordinates (bottom-left origin).
|
|
4
|
+
*
|
|
5
|
+
* Template: (0, 0) = top-left of content area, Y goes down.
|
|
6
|
+
* pdf-lib: (0, 0) = bottom-left of page, Y goes up.
|
|
7
|
+
*
|
|
8
|
+
* Returns the top of the element in pdf-lib coordinates.
|
|
9
|
+
*/
|
|
10
|
+
export declare function templateToPdf(templateX: number, templateY: number, pageHeight: number, marginTop: number, marginLeft: number): {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=coordinate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate.d.ts","sourceRoot":"","sources":["../src/coordinate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAK1B"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate from template coordinates (top-left origin) to pdf-lib
|
|
3
|
+
* coordinates (bottom-left origin).
|
|
4
|
+
*
|
|
5
|
+
* Template: (0, 0) = top-left of content area, Y goes down.
|
|
6
|
+
* pdf-lib: (0, 0) = bottom-left of page, Y goes up.
|
|
7
|
+
*
|
|
8
|
+
* Returns the top of the element in pdf-lib coordinates.
|
|
9
|
+
*/
|
|
10
|
+
export function templateToPdf(templateX, templateY, pageHeight, marginTop, marginLeft) {
|
|
11
|
+
return {
|
|
12
|
+
x: marginLeft + templateX,
|
|
13
|
+
y: pageHeight - marginTop - templateY,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=coordinate.js.map
|