@ic-labs/invoice-kit 0.1.13 → 0.1.15
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/README.md +43 -2
- package/dist/core/types.d.ts +23 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/renderers/pdf-support.d.ts +5 -5
- package/dist/renderers/pdf-support.d.ts.map +1 -1
- package/dist/renderers/pdf-support.js +33 -17
- package/dist/renderers/pdf-support.js.map +1 -1
- package/dist/renderers/pdf.d.ts.map +1 -1
- package/dist/renderers/pdf.js +120 -87
- package/dist/renderers/pdf.js.map +1 -1
- package/dist/vendor/DejaVu-LICENSE.txt +187 -0
- package/dist/vendor/PDFKit-LICENSE.txt +8 -0
- package/dist/vendor/dejavu-fonts.cjs +6 -0
- package/dist/vendor/pdfkit.cjs +50446 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -120,6 +120,47 @@ await invoice.toPDF({
|
|
|
120
120
|
});
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
+
### PDF spacing
|
|
124
|
+
|
|
125
|
+
The current roomy layout is the default. You can override individual spacing values through `toPDF({ spacing })`; omitted values keep their defaults.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
await invoice.toPDF({
|
|
129
|
+
outputPath: "./invoice.pdf",
|
|
130
|
+
spacing: {
|
|
131
|
+
headerToParties: 40,
|
|
132
|
+
partiesToTable: 30,
|
|
133
|
+
tableToSummary: 26,
|
|
134
|
+
detailLineGap: 3,
|
|
135
|
+
tableRowMinHeight: 34
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
All values use PDF points (`72` points = `1` inch) and must be finite, non-negative numbers.
|
|
141
|
+
|
|
142
|
+
| Option | Default | Controls |
|
|
143
|
+
| --- | ---: | --- |
|
|
144
|
+
| `issuerNameToDetails` | `10` | Issuer name to issuer address/details |
|
|
145
|
+
| `titleToMetadata` | `10` | Document title to number/date metadata |
|
|
146
|
+
| `metadataRowGap` | `7` | Space between metadata rows |
|
|
147
|
+
| `headerToParties` | `30` (`34` for delivery/return notes) | Header to seller/client section |
|
|
148
|
+
| `partyLabelToDetails` | `22` | Seller/client label to its details |
|
|
149
|
+
| `partiesToTable` | `24` | Seller/client section to item table |
|
|
150
|
+
| `headerToTable` | `20` (`24` for delivery/return notes) | Header to table when no party section exists |
|
|
151
|
+
| `tableToSummary` | `20` | Table to the aligned bank/totals row |
|
|
152
|
+
| `bankLabelToDetails` | `18` | Bank heading to bank details |
|
|
153
|
+
| `bankToNotes` | `16` | Bank details to notes |
|
|
154
|
+
| `notesLabelToDetails` | `18` | Notes heading to notes text |
|
|
155
|
+
| `detailLineGap` | `2` | Line spacing inside issuer, party, bank, and table details |
|
|
156
|
+
| `tableHeaderHeight` | `28` | Item-table header height |
|
|
157
|
+
| `tableRowMinHeight` | `30` | Minimum item-row height |
|
|
158
|
+
| `tableTextTopPadding` | `9` | Text offset from the top of item rows |
|
|
159
|
+
| `summaryRowHeight` | `26` | Height of each totals row |
|
|
160
|
+
| `summaryBottomGap` | `16` | Extra space below the left-side bank/notes content |
|
|
161
|
+
|
|
162
|
+
Larger values may move sections to another page. Automatic table and section pagination remains active.
|
|
163
|
+
|
|
123
164
|
## Document Factories
|
|
124
165
|
|
|
125
166
|
### `createInvoice(input)`
|
|
@@ -422,7 +463,7 @@ const quote = createQuote({
|
|
|
422
463
|
|
|
423
464
|
### Arabic PDF rendering
|
|
424
465
|
|
|
425
|
-
Arabic labels are supported out of the box. The renderer first tries your explicit `toPDF({ fonts })` values, then falls back to
|
|
466
|
+
Arabic labels are supported out of the box. The renderer first tries your explicit `toPDF({ fonts })` values, then falls back to DejaVu Sans font bytes embedded in the package. The fallback does not require font files from `node_modules` at runtime.
|
|
426
467
|
|
|
427
468
|
```ts
|
|
428
469
|
await quote.toPDF({
|
|
@@ -434,7 +475,7 @@ await quote.toPDF({
|
|
|
434
475
|
});
|
|
435
476
|
```
|
|
436
477
|
|
|
437
|
-
You can still provide your own Arabic-capable
|
|
478
|
+
You can still provide your own Arabic-capable fonts when you want a different visual style. Custom font values may be filesystem paths, `Uint8Array` instances, or `ArrayBuffer` instances.
|
|
438
479
|
|
|
439
480
|
## Testing
|
|
440
481
|
|
package/dist/core/types.d.ts
CHANGED
|
@@ -113,9 +113,30 @@ export interface BusinessDocumentData {
|
|
|
113
113
|
export interface PdfRenderOptions {
|
|
114
114
|
outputPath?: string;
|
|
115
115
|
fonts?: {
|
|
116
|
-
regular?:
|
|
117
|
-
bold?:
|
|
116
|
+
regular?: PdfFontSource;
|
|
117
|
+
bold?: PdfFontSource;
|
|
118
118
|
};
|
|
119
|
+
spacing?: PdfSpacingOptions;
|
|
120
|
+
}
|
|
121
|
+
export type PdfFontSource = string | Uint8Array | ArrayBuffer;
|
|
122
|
+
export interface PdfSpacingOptions {
|
|
123
|
+
issuerNameToDetails?: number;
|
|
124
|
+
titleToMetadata?: number;
|
|
125
|
+
metadataRowGap?: number;
|
|
126
|
+
headerToParties?: number;
|
|
127
|
+
partyLabelToDetails?: number;
|
|
128
|
+
partiesToTable?: number;
|
|
129
|
+
headerToTable?: number;
|
|
130
|
+
tableToSummary?: number;
|
|
131
|
+
bankLabelToDetails?: number;
|
|
132
|
+
bankToNotes?: number;
|
|
133
|
+
notesLabelToDetails?: number;
|
|
134
|
+
detailLineGap?: number;
|
|
135
|
+
tableHeaderHeight?: number;
|
|
136
|
+
tableRowMinHeight?: number;
|
|
137
|
+
tableTextTopPadding?: number;
|
|
138
|
+
summaryRowHeight?: number;
|
|
139
|
+
summaryBottomGap?: number;
|
|
119
140
|
}
|
|
120
141
|
export interface TemplateLabels {
|
|
121
142
|
documentTitle: string;
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,YAAY,CAAC;AAEjG,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3C,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,KAAK;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,OAAO,CAAC;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,qBAAqB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BankInfo, BusinessDocumentData, DocumentColors, Party, PdfRenderOptions } from "../core/types.js";
|
|
1
|
+
import type { BankInfo, BusinessDocumentData, DocumentColors, Party, PdfFontSource, PdfRenderOptions } from "../core/types.js";
|
|
2
2
|
import { getLabels } from "../locales/index.js";
|
|
3
3
|
export declare const PAGE: {
|
|
4
4
|
margin: number;
|
|
@@ -10,11 +10,11 @@ export declare const PAGE: {
|
|
|
10
10
|
};
|
|
11
11
|
export declare const DEFAULT_COLORS: Required<DocumentColors>;
|
|
12
12
|
export declare const collectPdf: (doc: PDFKit.PDFDocument) => Promise<Uint8Array>;
|
|
13
|
-
export declare const fetchLogo: (logoUrl: string) => Promise<
|
|
14
|
-
export declare const useFont: (doc: PDFKit.PDFDocument,
|
|
13
|
+
export declare const fetchLogo: (logoUrl: string) => Promise<ArrayBuffer>;
|
|
14
|
+
export declare const useFont: (doc: PDFKit.PDFDocument, fontSource: PdfFontSource | undefined, fallback: "Helvetica" | "Helvetica-Bold") => void;
|
|
15
15
|
export declare const resolvePdfFonts: (document: BusinessDocumentData, options?: PdfRenderOptions) => {
|
|
16
|
-
regular?:
|
|
17
|
-
bold?:
|
|
16
|
+
regular?: PdfFontSource;
|
|
17
|
+
bold?: PdfFontSource;
|
|
18
18
|
} | undefined;
|
|
19
19
|
export declare const truncateText: (doc: PDFKit.PDFDocument, value: string, width: number) => string;
|
|
20
20
|
export declare const drawFixedText: (doc: PDFKit.PDFDocument, text: string, x: number, y: number, options: PDFKit.Mixins.TextOptions) => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-support.d.ts","sourceRoot":"","sources":["../../src/renderers/pdf-support.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"pdf-support.d.ts","sourceRoot":"","sources":["../../src/renderers/pdf-support.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC/H,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAsBhD,eAAO,MAAM,IAAI;;;;;;;CAOhB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,cAAc,CAQnD,CAAC;AAqCF,eAAO,MAAM,UAAU,GAAU,KAAK,MAAM,CAAC,WAAW,KAAG,OAAO,CAAC,UAAU,CAazE,CAAC;AAEL,eAAO,MAAM,SAAS,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,WAAW,CAwBpE,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,CAAC,WAAW,EAAE,YAAY,aAAa,GAAG,SAAS,EAAE,UAAU,WAAW,GAAG,gBAAgB,KAAG,IAUlI,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,oBAAoB,EAC9B,UAAU,gBAAgB,KACzB;IAAE,OAAO,CAAC,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,SAYtD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,MAWpF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,KAAK,MAAM,CAAC,WAAW,EACvB,MAAM,MAAM,EACZ,GAAG,MAAM,EACT,GAAG,MAAM,EACT,SAAS,MAAM,CAAC,MAAM,CAAC,WAAW,KACjC,MAWF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,KAAG,MAItC,CAAC;AAEhB,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,CAAC,WAAW,EAAE,GAAG,MAAM,EAAE,gBAAgB,MAAM,KAAG,MAS/F,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,KAAK,MAAM,CAAC,WAAW,EACvB,GAAG,MAAM,EACT,GAAG,MAAM,EACT,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,MAAM,GAAG,OAAO,EACvB,OAAO,MAAM,KACZ,MAGF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,cAAc,KAAG,QAAQ,CAAC,cAAc,CAG7E,CAAC;AAaH,eAAO,MAAM,eAAe,GAC1B,KAAK,MAAM,CAAC,WAAW,EACvB,OAAO,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAA;CAAE,CAAC,EACjF,WAAW,MAAM,KAChB,MAEU,CAAC;AAEd,eAAO,MAAM,eAAe,GAAI,OAAO,KAAK,GAAG,SAAS,EAAE,QAAQ,UAAU,CAAC,OAAO,SAAS,CAAC,EAAE,qBAAkB,KAAG,MAAM,EAgB1H,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,UAAU,QAAQ,EAAE,QAAQ,UAAU,CAAC,OAAO,SAAS,CAAC,KAAG,MAAM,EAW/F,CAAC"}
|
|
@@ -1,6 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
2
|
import { getLabels } from "../locales/index.js";
|
|
3
|
-
|
|
3
|
+
import bundledFontBase64 from "../vendor/dejavu-fonts.cjs";
|
|
4
|
+
const STANDARD_PDF_FONTS = new Set([
|
|
5
|
+
"Courier",
|
|
6
|
+
"Courier-Bold",
|
|
7
|
+
"Courier-Oblique",
|
|
8
|
+
"Courier-BoldOblique",
|
|
9
|
+
"Helvetica",
|
|
10
|
+
"Helvetica-Bold",
|
|
11
|
+
"Helvetica-Oblique",
|
|
12
|
+
"Helvetica-BoldOblique",
|
|
13
|
+
"Times-Roman",
|
|
14
|
+
"Times-Bold",
|
|
15
|
+
"Times-Italic",
|
|
16
|
+
"Times-BoldItalic",
|
|
17
|
+
"Symbol",
|
|
18
|
+
"ZapfDingbats"
|
|
19
|
+
]);
|
|
4
20
|
export const PAGE = {
|
|
5
21
|
margin: 48,
|
|
6
22
|
width: 595.28,
|
|
@@ -36,16 +52,13 @@ const normalizeFontPair = (regular, bold) => {
|
|
|
36
52
|
bold: bold ?? regular
|
|
37
53
|
};
|
|
38
54
|
};
|
|
55
|
+
let bundledArabicFonts;
|
|
39
56
|
const resolveBundledArabicFonts = () => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
throw new Error("Unable to resolve the bundled Arabic font fallback. Reinstall dependencies or provide options.fonts.regular/options.fonts.bold explicitly.");
|
|
48
|
-
}
|
|
57
|
+
bundledArabicFonts ??= {
|
|
58
|
+
regular: Buffer.from(bundledFontBase64.regular, "base64"),
|
|
59
|
+
bold: Buffer.from(bundledFontBase64.bold, "base64")
|
|
60
|
+
};
|
|
61
|
+
return bundledArabicFonts;
|
|
49
62
|
};
|
|
50
63
|
export const collectPdf = async (doc) => new Promise((resolve, reject) => {
|
|
51
64
|
const chunks = [];
|
|
@@ -66,20 +79,23 @@ export const fetchLogo = async (logoUrl) => {
|
|
|
66
79
|
const buffer = Buffer.from(arrayBuffer);
|
|
67
80
|
const contentType = response.headers.get("content-type") ?? "";
|
|
68
81
|
if (isPngBuffer(buffer) || isJpegBuffer(buffer)) {
|
|
69
|
-
return
|
|
82
|
+
return arrayBuffer;
|
|
70
83
|
}
|
|
71
84
|
try {
|
|
72
85
|
const { default: sharp } = await import("sharp");
|
|
73
86
|
const pipeline = contentType.includes("svg") ? sharp(buffer, { density: 300 }) : sharp(buffer);
|
|
74
|
-
return await pipeline.png().toBuffer();
|
|
87
|
+
return new Uint8Array(await pipeline.png().toBuffer()).buffer;
|
|
75
88
|
}
|
|
76
89
|
catch {
|
|
77
90
|
throw new Error(`Unsupported logo format at ${logoUrl}. Remote logos currently support PNG, JPEG, SVG, and WEBP.`);
|
|
78
91
|
}
|
|
79
92
|
};
|
|
80
|
-
export const useFont = (doc,
|
|
81
|
-
if (
|
|
82
|
-
|
|
93
|
+
export const useFont = (doc, fontSource, fallback) => {
|
|
94
|
+
if (fontSource) {
|
|
95
|
+
const resolvedFont = typeof fontSource === "string" && !STANDARD_PDF_FONTS.has(fontSource)
|
|
96
|
+
? readFileSync(fontSource)
|
|
97
|
+
: fontSource;
|
|
98
|
+
doc.font(resolvedFont);
|
|
83
99
|
return;
|
|
84
100
|
}
|
|
85
101
|
doc.font(fallback);
|
|
@@ -136,7 +152,7 @@ export const resolveColors = (colors) => ({
|
|
|
136
152
|
});
|
|
137
153
|
const getWrappedRowHeight = (doc, text, width, minHeight, options) => {
|
|
138
154
|
const textHeight = doc.heightOfString(text, { ...options, width });
|
|
139
|
-
return Math.max(minHeight, Math.ceil(textHeight +
|
|
155
|
+
return Math.max(minHeight, Math.ceil(textHeight + 16));
|
|
140
156
|
};
|
|
141
157
|
export const getMaxRowHeight = (doc, cells, minHeight) => cells.reduce((maxHeight, cell) => (Math.max(maxHeight, getWrappedRowHeight(doc, cell.text, cell.width, minHeight, cell.options))), minHeight);
|
|
142
158
|
export const buildPartyLines = (party, labels, includeName = true) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-support.js","sourceRoot":"","sources":["../../src/renderers/pdf-support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pdf-support.js","sourceRoot":"","sources":["../../src/renderers/pdf-support.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../src/renderers/pdf.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../src/renderers/pdf.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAgC/E,eAAO,MAAM,iBAAiB,GAC5B,UAAU,oBAAoB,EAC9B,UAAU,gBAAgB,KACzB,OAAO,CAAC,UAAU,CAiZpB,CAAC"}
|
package/dist/renderers/pdf.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import PDFDocument from "pdfkit";
|
|
1
|
+
import PDFDocument from "../vendor/pdfkit.cjs";
|
|
2
2
|
import { getLabels } from "../locales/index.js";
|
|
3
3
|
import { formatDate, formatMoney } from "../utils/formatting.js";
|
|
4
4
|
import { PAGE, buildBankLines, buildPartyLines, collectPdf, drawFixedText, drawLabelValue, ensureSectionSpace, fetchLogo, getMaxRowHeight, normalizeFooterText, resolveColors, resolvePdfFonts, truncateText, useFont } from "./pdf-support.js";
|
|
5
|
+
const resolveSpacing = (value, fallback, name) => {
|
|
6
|
+
if (value === undefined) {
|
|
7
|
+
return fallback;
|
|
8
|
+
}
|
|
9
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
10
|
+
throw new Error(`options.spacing.${name} must be a non-negative finite number.`);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
5
14
|
export const renderDocumentPdf = async (document, options) => {
|
|
6
15
|
const labels = getLabels(document.locale);
|
|
7
16
|
const colors = resolveColors(document.colors);
|
|
@@ -15,20 +24,27 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
15
24
|
const metaTopX = rightColumnX;
|
|
16
25
|
const tableX = PAGE.margin;
|
|
17
26
|
const tableWidth = PAGE.width - PAGE.margin * 2;
|
|
27
|
+
const spacing = options?.spacing;
|
|
18
28
|
const logoFit = isStockMovementDocument ? [80, 80] : [72, 72];
|
|
19
29
|
const issuerNameOffsetY = isStockMovementDocument ? 3 : 1;
|
|
20
|
-
const issuerNameGapY =
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
30
|
+
const issuerNameGapY = resolveSpacing(spacing?.issuerNameToDetails, 10, "issuerNameToDetails");
|
|
31
|
+
const configuredTitleMetaGapY = resolveSpacing(spacing?.titleToMetadata, 10, "titleToMetadata");
|
|
32
|
+
const titleMetaGapY = document.title ? configuredTitleMetaGapY : 0;
|
|
33
|
+
const metaRowGapY = resolveSpacing(spacing?.metadataRowGap, 7, "metadataRowGap");
|
|
34
|
+
const sectionGapY = resolveSpacing(spacing?.headerToParties, isStockMovementDocument ? 34 : 30, "headerToParties");
|
|
35
|
+
const sectionBodyOffsetY = resolveSpacing(spacing?.partyLabelToDetails, 22, "partyLabelToDetails");
|
|
36
|
+
const sectionAfterGapY = resolveSpacing(spacing?.partiesToTable, 24, "partiesToTable");
|
|
37
|
+
const bankDetailsBodyOffsetY = resolveSpacing(spacing?.bankLabelToDetails, 18, "bankLabelToDetails");
|
|
38
|
+
const bankNotesGapY = resolveSpacing(spacing?.bankToNotes, 16, "bankToNotes");
|
|
39
|
+
const tableTopGapY = resolveSpacing(spacing?.headerToTable, isStockMovementDocument ? 24 : 20, "headerToTable");
|
|
40
|
+
const trailingSectionGapY = resolveSpacing(spacing?.tableToSummary, 20, "tableToSummary");
|
|
41
|
+
const notesBodyOffsetY = resolveSpacing(spacing?.notesLabelToDetails, 18, "notesLabelToDetails");
|
|
42
|
+
const trailingBottomGapY = resolveSpacing(spacing?.summaryBottomGap, 16, "summaryBottomGap");
|
|
43
|
+
const detailLineGapY = resolveSpacing(spacing?.detailLineGap, 2, "detailLineGap");
|
|
44
|
+
const tableHeaderHeight = resolveSpacing(spacing?.tableHeaderHeight, 28, "tableHeaderHeight");
|
|
45
|
+
const tableRowMinHeight = resolveSpacing(spacing?.tableRowMinHeight, 30, "tableRowMinHeight");
|
|
46
|
+
const tableTextOffsetY = resolveSpacing(spacing?.tableTextTopPadding, 9, "tableTextTopPadding");
|
|
47
|
+
const summaryRowHeight = resolveSpacing(spacing?.summaryRowHeight, 26, "summaryRowHeight");
|
|
32
48
|
const contentBottomY = PAGE.height - PAGE.margin - 8;
|
|
33
49
|
// pdfkit is chosen because it stays lightweight while supporting custom TTF/OTF fonts,
|
|
34
50
|
// which is necessary for Arabic-capable PDF output in a Node-only library.
|
|
@@ -52,7 +68,7 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
52
68
|
}
|
|
53
69
|
doc.addPage();
|
|
54
70
|
drawHeader(PAGE.margin);
|
|
55
|
-
return PAGE.margin +
|
|
71
|
+
return PAGE.margin + tableHeaderHeight;
|
|
56
72
|
};
|
|
57
73
|
if (logoBuffer) {
|
|
58
74
|
doc.image(logoBuffer, leftColumnX, PAGE.headerTop, {
|
|
@@ -76,7 +92,7 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
76
92
|
issuerHeaderBottomY = drawFixedText(doc, issuerLines.join("\n"), issuerTextX, issuerName ? issuerHeaderBottomY + issuerNameGapY : PAGE.headerTop, {
|
|
77
93
|
width: issuerTextWidth,
|
|
78
94
|
align,
|
|
79
|
-
lineGap:
|
|
95
|
+
lineGap: detailLineGapY
|
|
80
96
|
});
|
|
81
97
|
}
|
|
82
98
|
const sellerLines = buildPartyLines(document.seller, labels);
|
|
@@ -113,7 +129,7 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
113
129
|
const minimumHeaderBottomY = PAGE.headerTop + (isStockMovementDocument ? 72 : 48);
|
|
114
130
|
const headerBottomY = Math.max(metaBottomY, issuerHeaderBottomY, minimumHeaderBottomY);
|
|
115
131
|
let y = headerBottomY + tableTopGapY;
|
|
116
|
-
if (sellerLines.length > 0 || clientLines.length > 0
|
|
132
|
+
if (sellerLines.length > 0 || clientLines.length > 0) {
|
|
117
133
|
const sectionsTopY = headerBottomY + sectionGapY;
|
|
118
134
|
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
119
135
|
doc.fillColor(colors.mutedText).fontSize(10);
|
|
@@ -130,19 +146,7 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
130
146
|
leftSectionBottomY = drawFixedText(doc, sellerLines.join("\n"), leftColumnX, sectionsTopY + sectionBodyOffsetY, {
|
|
131
147
|
width: 270,
|
|
132
148
|
align,
|
|
133
|
-
lineGap:
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
if (bankLines) {
|
|
137
|
-
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
138
|
-
doc.fillColor(colors.mutedText).fontSize(9);
|
|
139
|
-
drawFixedText(doc, labels.bankDetails, leftColumnX, leftSectionBottomY + bankSectionGapY, { width: columnWidth, align });
|
|
140
|
-
useFont(doc, fonts?.regular, "Helvetica");
|
|
141
|
-
doc.fillColor(colors.text).fontSize(9);
|
|
142
|
-
leftSectionBottomY = drawFixedText(doc, bankLines.join("\n"), leftColumnX, leftSectionBottomY + bankSectionBodyOffsetY, {
|
|
143
|
-
width: 270,
|
|
144
|
-
align,
|
|
145
|
-
lineGap: 1
|
|
149
|
+
lineGap: detailLineGapY
|
|
146
150
|
});
|
|
147
151
|
}
|
|
148
152
|
let clientBottomY = sectionsTopY;
|
|
@@ -150,7 +154,7 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
150
154
|
clientBottomY = drawFixedText(doc, clientLines.join("\n"), rightColumnX, sectionsTopY + sectionBodyOffsetY, {
|
|
151
155
|
width: columnWidth,
|
|
152
156
|
align,
|
|
153
|
-
lineGap:
|
|
157
|
+
lineGap: detailLineGapY
|
|
154
158
|
});
|
|
155
159
|
}
|
|
156
160
|
y = Math.max(leftSectionBottomY, clientBottomY) + sectionAfterGapY;
|
|
@@ -166,18 +170,18 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
166
170
|
quantityWidth: 50
|
|
167
171
|
};
|
|
168
172
|
const drawHeader = (headerY) => {
|
|
169
|
-
doc.fillColor(colors.primary).rect(tableX, headerY, tableWidth,
|
|
173
|
+
doc.fillColor(colors.primary).rect(tableX, headerY, tableWidth, tableHeaderHeight).fill();
|
|
170
174
|
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
171
175
|
doc.fillColor(colors.onPrimary).fontSize(10);
|
|
172
|
-
drawFixedText(doc, labels.item, columns.itemX, headerY +
|
|
173
|
-
drawFixedText(doc, labels.quantity, columns.quantityX, headerY +
|
|
176
|
+
drawFixedText(doc, labels.item, columns.itemX, headerY + 8, { width: columns.itemWidth, align });
|
|
177
|
+
drawFixedText(doc, labels.quantity, columns.quantityX, headerY + 8, { width: columns.quantityWidth, align: "right" });
|
|
174
178
|
};
|
|
175
|
-
if (y +
|
|
179
|
+
if (y + tableHeaderHeight > contentBottomY) {
|
|
176
180
|
doc.addPage();
|
|
177
181
|
y = PAGE.margin;
|
|
178
182
|
}
|
|
179
183
|
drawHeader(y);
|
|
180
|
-
y +=
|
|
184
|
+
y += tableHeaderHeight;
|
|
181
185
|
useFont(doc, fonts?.regular, "Helvetica");
|
|
182
186
|
for (const item of items) {
|
|
183
187
|
const itemLabel = item.description ? `${item.name} - ${item.description}` : item.name;
|
|
@@ -185,18 +189,18 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
185
189
|
const rowHeight = getMaxRowHeight(doc, [
|
|
186
190
|
{ text: itemLabel, width: columns.itemWidth, options: { align, lineGap: 1 } },
|
|
187
191
|
{ text: quantityLabel, width: columns.quantityWidth, options: { align: "right", lineGap: 1 } }
|
|
188
|
-
],
|
|
192
|
+
], tableRowMinHeight);
|
|
189
193
|
y = ensureTableRowSpace(y, rowHeight, drawHeader);
|
|
190
194
|
doc.strokeColor(colors.border).lineWidth(1).rect(tableX, y, tableWidth, rowHeight).stroke();
|
|
191
195
|
doc.fillColor(colors.text).fontSize(10);
|
|
192
|
-
drawFixedText(doc, truncateText(doc, itemLabel, columns.itemWidth), columns.itemX, y +
|
|
196
|
+
drawFixedText(doc, truncateText(doc, itemLabel, columns.itemWidth), columns.itemX, y + tableTextOffsetY, {
|
|
193
197
|
width: columns.itemWidth,
|
|
194
198
|
align
|
|
195
199
|
});
|
|
196
|
-
drawFixedText(doc, quantityLabel, columns.quantityX, y +
|
|
200
|
+
drawFixedText(doc, quantityLabel, columns.quantityX, y + tableTextOffsetY, {
|
|
197
201
|
width: columns.quantityWidth,
|
|
198
202
|
align: "right",
|
|
199
|
-
lineGap:
|
|
203
|
+
lineGap: detailLineGapY
|
|
200
204
|
});
|
|
201
205
|
y += rowHeight;
|
|
202
206
|
}
|
|
@@ -213,20 +217,20 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
213
217
|
amountWidth: 95
|
|
214
218
|
};
|
|
215
219
|
const drawHeader = (headerY) => {
|
|
216
|
-
doc.fillColor(colors.primary).rect(tableX, headerY, tableWidth,
|
|
220
|
+
doc.fillColor(colors.primary).rect(tableX, headerY, tableWidth, tableHeaderHeight).fill();
|
|
217
221
|
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
218
222
|
doc.fillColor(colors.onPrimary).fontSize(10);
|
|
219
|
-
drawFixedText(doc, labels.item, columns.itemX, headerY +
|
|
220
|
-
drawFixedText(doc, labels.quantity, columns.quantityX, headerY +
|
|
221
|
-
drawFixedText(doc, labels.unitPrice, columns.unitPriceX, headerY +
|
|
222
|
-
drawFixedText(doc, labels.amount, columns.amountX, headerY +
|
|
223
|
+
drawFixedText(doc, labels.item, columns.itemX, headerY + 8, { width: columns.itemWidth, align });
|
|
224
|
+
drawFixedText(doc, labels.quantity, columns.quantityX, headerY + 8, { width: columns.quantityWidth, align: "right" });
|
|
225
|
+
drawFixedText(doc, labels.unitPrice, columns.unitPriceX, headerY + 8, { width: columns.unitPriceWidth, align: "right" });
|
|
226
|
+
drawFixedText(doc, labels.amount, columns.amountX, headerY + 8, { width: columns.amountWidth, align: "right" });
|
|
223
227
|
};
|
|
224
|
-
if (y +
|
|
228
|
+
if (y + tableHeaderHeight > contentBottomY) {
|
|
225
229
|
doc.addPage();
|
|
226
230
|
y = PAGE.margin;
|
|
227
231
|
}
|
|
228
232
|
drawHeader(y);
|
|
229
|
-
y +=
|
|
233
|
+
y += tableHeaderHeight;
|
|
230
234
|
useFont(doc, fonts?.regular, "Helvetica");
|
|
231
235
|
for (const item of items) {
|
|
232
236
|
const itemLabel = item.description ? `${item.name} - ${item.description}` : item.name;
|
|
@@ -234,25 +238,25 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
234
238
|
const rowHeight = getMaxRowHeight(doc, [
|
|
235
239
|
{ text: itemLabel, width: columns.itemWidth, options: { align, lineGap: 1 } },
|
|
236
240
|
{ text: quantityLabel, width: columns.quantityWidth, options: { align: "right", lineGap: 1 } }
|
|
237
|
-
],
|
|
241
|
+
], tableRowMinHeight);
|
|
238
242
|
y = ensureTableRowSpace(y, rowHeight, drawHeader);
|
|
239
243
|
doc.strokeColor(colors.border).lineWidth(1).rect(tableX, y, tableWidth, rowHeight).stroke();
|
|
240
244
|
doc.fillColor(colors.text).fontSize(10);
|
|
241
|
-
drawFixedText(doc, itemLabel, columns.itemX, y +
|
|
245
|
+
drawFixedText(doc, itemLabel, columns.itemX, y + tableTextOffsetY, {
|
|
242
246
|
width: columns.itemWidth,
|
|
243
247
|
align,
|
|
244
|
-
lineGap:
|
|
248
|
+
lineGap: detailLineGapY
|
|
245
249
|
});
|
|
246
|
-
drawFixedText(doc, quantityLabel, columns.quantityX, y +
|
|
250
|
+
drawFixedText(doc, quantityLabel, columns.quantityX, y + tableTextOffsetY, {
|
|
247
251
|
width: columns.quantityWidth,
|
|
248
252
|
align: "right",
|
|
249
|
-
lineGap:
|
|
253
|
+
lineGap: detailLineGapY
|
|
250
254
|
});
|
|
251
|
-
drawFixedText(doc, truncateText(doc, formatMoney(item.unitPrice, document.locale, document.currency ?? "MAD"), columns.unitPriceWidth), columns.unitPriceX, y +
|
|
255
|
+
drawFixedText(doc, truncateText(doc, formatMoney(item.unitPrice, document.locale, document.currency ?? "MAD"), columns.unitPriceWidth), columns.unitPriceX, y + tableTextOffsetY, {
|
|
252
256
|
width: columns.unitPriceWidth,
|
|
253
257
|
align: "right"
|
|
254
258
|
});
|
|
255
|
-
drawFixedText(doc, truncateText(doc, formatMoney(item.lineTotal, document.locale, document.currency ?? "MAD"), columns.amountWidth), columns.amountX, y +
|
|
259
|
+
drawFixedText(doc, truncateText(doc, formatMoney(item.lineTotal, document.locale, document.currency ?? "MAD"), columns.amountWidth), columns.amountX, y + tableTextOffsetY, {
|
|
256
260
|
width: columns.amountWidth,
|
|
257
261
|
align: "right"
|
|
258
262
|
});
|
|
@@ -270,13 +274,59 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
270
274
|
if (document.notes) {
|
|
271
275
|
notes.push(`${labels.notes}: ${document.notes}`);
|
|
272
276
|
}
|
|
277
|
+
const bankText = bankLines?.join("\n");
|
|
278
|
+
const leftDetailsWidth = tableWidth - 236;
|
|
279
|
+
useFont(doc, fonts?.regular, "Helvetica");
|
|
280
|
+
doc.fontSize(9);
|
|
281
|
+
const bankDetailsHeight = bankText
|
|
282
|
+
? bankDetailsBodyOffsetY + doc.heightOfString(bankText, {
|
|
283
|
+
width: leftDetailsWidth,
|
|
284
|
+
align,
|
|
285
|
+
lineGap: detailLineGapY
|
|
286
|
+
})
|
|
287
|
+
: 0;
|
|
288
|
+
const notesHeight = notes.length > 0
|
|
289
|
+
? notesBodyOffsetY + doc.heightOfString(notes.join("\n"), {
|
|
290
|
+
width: leftDetailsWidth,
|
|
291
|
+
align,
|
|
292
|
+
lineGap: 1
|
|
293
|
+
})
|
|
294
|
+
: 0;
|
|
295
|
+
const leftDetailsHeight = bankDetailsHeight
|
|
296
|
+
+ (bankText && notes.length > 0 ? bankNotesGapY : 0)
|
|
297
|
+
+ notesHeight;
|
|
298
|
+
const drawLeftDetails = (startY) => {
|
|
299
|
+
let leftBottomY = startY;
|
|
300
|
+
if (bankText) {
|
|
301
|
+
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
302
|
+
doc.fillColor(colors.mutedText).fontSize(9);
|
|
303
|
+
drawFixedText(doc, labels.bankDetails, tableX, startY, { width: leftDetailsWidth, align });
|
|
304
|
+
useFont(doc, fonts?.regular, "Helvetica");
|
|
305
|
+
doc.fillColor(colors.text).fontSize(9);
|
|
306
|
+
leftBottomY = drawFixedText(doc, bankText, tableX, startY + bankDetailsBodyOffsetY, {
|
|
307
|
+
width: leftDetailsWidth,
|
|
308
|
+
align,
|
|
309
|
+
lineGap: detailLineGapY
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (notes.length > 0) {
|
|
313
|
+
const notesTopY = bankText ? leftBottomY + bankNotesGapY : startY;
|
|
314
|
+
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
315
|
+
doc.fillColor(colors.mutedText).fontSize(10);
|
|
316
|
+
drawFixedText(doc, labels.notes, tableX, notesTopY, { width: leftDetailsWidth, align });
|
|
317
|
+
useFont(doc, fonts?.regular, "Helvetica");
|
|
318
|
+
doc.fillColor(colors.text).fontSize(9);
|
|
319
|
+
leftBottomY = drawFixedText(doc, notes.join("\n"), tableX, notesTopY + notesBodyOffsetY, {
|
|
320
|
+
width: leftDetailsWidth,
|
|
321
|
+
align,
|
|
322
|
+
lineGap: 1
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
return leftBottomY;
|
|
326
|
+
};
|
|
273
327
|
if (!isStockMovementDocument && document.totals) {
|
|
274
|
-
const totalsHeight =
|
|
275
|
-
|
|
276
|
-
const notesHeight = notes.length > 0
|
|
277
|
-
? 12 + 12 + doc.heightOfString(notes.join("\n"), { width: notesWidth, align, lineGap: 1 }) + 8
|
|
278
|
-
: 0;
|
|
279
|
-
y = ensureSectionSpace(doc, y + trailingSectionGapY, Math.max(totalsHeight, notesHeight)) - trailingSectionGapY;
|
|
328
|
+
const totalsHeight = summaryRowHeight * 5;
|
|
329
|
+
y = ensureSectionSpace(doc, y + trailingSectionGapY, Math.max(totalsHeight, leftDetailsHeight)) - trailingSectionGapY;
|
|
280
330
|
const totalsX = PAGE.width - PAGE.margin - 220;
|
|
281
331
|
const totals = [
|
|
282
332
|
[labels.subtotal, formatMoney(document.totals.subtotal, document.locale, document.currency ?? "MAD")],
|
|
@@ -286,41 +336,24 @@ export const renderDocumentPdf = async (document, options) => {
|
|
|
286
336
|
[labels.total, formatMoney(document.totals.total, document.locale, document.currency ?? "MAD")]
|
|
287
337
|
];
|
|
288
338
|
y += trailingSectionGapY;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
useFont(doc, fonts?.bold, "Helvetica-Bold");
|
|
292
|
-
doc.fillColor(colors.mutedText).fontSize(10);
|
|
293
|
-
drawFixedText(doc, labels.notes, PAGE.margin, y, { width: notesWidth, align });
|
|
294
|
-
useFont(doc, fonts?.regular, "Helvetica");
|
|
295
|
-
doc.fillColor(colors.text).fontSize(9);
|
|
296
|
-
trailingBottomY = drawFixedText(doc, notes.join("\n"), PAGE.margin, y + notesBodyOffsetY, {
|
|
297
|
-
width: notesWidth,
|
|
298
|
-
align,
|
|
299
|
-
lineGap: 1
|
|
300
|
-
});
|
|
301
|
-
}
|
|
339
|
+
const trailingBottomY = drawLeftDetails(y);
|
|
340
|
+
let totalsY = y;
|
|
302
341
|
totals.forEach(([label, value], index) => {
|
|
303
342
|
const isTotal = index === totals.length - 1;
|
|
304
|
-
doc.fillColor(isTotal ? colors.primary : "white").rect(totalsX,
|
|
305
|
-
doc.strokeColor(colors.border).lineWidth(1).rect(totalsX,
|
|
343
|
+
doc.fillColor(isTotal ? colors.primary : "white").rect(totalsX, totalsY, 220, summaryRowHeight).fill();
|
|
344
|
+
doc.strokeColor(colors.border).lineWidth(1).rect(totalsX, totalsY, 220, summaryRowHeight).stroke();
|
|
306
345
|
useFont(doc, isTotal ? fonts?.bold : fonts?.regular, isTotal ? "Helvetica-Bold" : "Helvetica");
|
|
307
346
|
doc.fillColor(isTotal ? colors.onPrimary : colors.text).fontSize(10);
|
|
308
|
-
drawFixedText(doc, label, totalsX + 10,
|
|
309
|
-
drawFixedText(doc, truncateText(doc, value, 85), totalsX + 125,
|
|
310
|
-
|
|
347
|
+
drawFixedText(doc, label, totalsX + 10, totalsY + 9, { width: 105, align: "left" });
|
|
348
|
+
drawFixedText(doc, truncateText(doc, value, 85), totalsX + 125, totalsY + 9, { width: 85, align: "right" });
|
|
349
|
+
totalsY += summaryRowHeight;
|
|
311
350
|
});
|
|
312
|
-
y = Math.max(
|
|
351
|
+
y = Math.max(totalsY, trailingBottomY + trailingBottomGapY);
|
|
313
352
|
}
|
|
314
|
-
else if (
|
|
315
|
-
|
|
316
|
-
y = ensureSectionSpace(doc, y + trailingSectionGapY, notesHeight) - trailingSectionGapY;
|
|
353
|
+
else if (leftDetailsHeight > 0) {
|
|
354
|
+
y = ensureSectionSpace(doc, y + trailingSectionGapY, leftDetailsHeight) - trailingSectionGapY;
|
|
317
355
|
y += trailingSectionGapY;
|
|
318
|
-
|
|
319
|
-
doc.fillColor(colors.mutedText).fontSize(10);
|
|
320
|
-
drawFixedText(doc, labels.notes, PAGE.margin, y, { width: tableWidth, align });
|
|
321
|
-
useFont(doc, fonts?.regular, "Helvetica");
|
|
322
|
-
doc.fillColor(colors.text).fontSize(9);
|
|
323
|
-
drawFixedText(doc, notes.join("\n"), PAGE.margin, y + notesBodyOffsetY, { width: tableWidth, align, lineGap: 1 });
|
|
356
|
+
y = drawLeftDetails(y);
|
|
324
357
|
}
|
|
325
358
|
useFont(doc, fonts?.regular, "Helvetica");
|
|
326
359
|
const actualPageHeight = doc.page.height ?? 841.89;
|