@pdfme/generator 2.2.0 → 2.2.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.
Files changed (62) hide show
  1. package/dist/cjs/__tests__/generate.test.js.map +1 -1
  2. package/dist/cjs/src/builtInRenderer.js +9 -0
  3. package/dist/cjs/src/builtInRenderer.js.map +1 -0
  4. package/dist/cjs/src/generate.js +29 -30
  5. package/dist/cjs/src/generate.js.map +1 -1
  6. package/dist/cjs/src/pdfUtils.js +65 -0
  7. package/dist/cjs/src/pdfUtils.js.map +1 -0
  8. package/dist/cjs/src/renderUtils.js +65 -0
  9. package/dist/cjs/src/renderUtils.js.map +1 -0
  10. package/dist/cjs/src/renders/barcodes.js +37 -0
  11. package/dist/cjs/src/renders/barcodes.js.map +1 -0
  12. package/dist/cjs/src/renders/image.js +34 -0
  13. package/dist/cjs/src/renders/image.js.map +1 -0
  14. package/dist/cjs/src/renders/text.js +86 -0
  15. package/dist/cjs/src/renders/text.js.map +1 -0
  16. package/dist/cjs/src/types.js +3 -0
  17. package/dist/cjs/src/types.js.map +1 -0
  18. package/dist/esm/__tests__/generate.test.js.map +1 -1
  19. package/dist/esm/src/builtInRenderer.js +7 -0
  20. package/dist/esm/src/builtInRenderer.js.map +1 -0
  21. package/dist/esm/src/generate.js +23 -27
  22. package/dist/esm/src/generate.js.map +1 -1
  23. package/dist/esm/src/pdfUtils.js +59 -0
  24. package/dist/esm/src/pdfUtils.js.map +1 -0
  25. package/dist/esm/src/renderUtils.js +56 -0
  26. package/dist/esm/src/renderUtils.js.map +1 -0
  27. package/dist/esm/src/renders/barcodes.js +33 -0
  28. package/dist/esm/src/renders/barcodes.js.map +1 -0
  29. package/dist/esm/src/renders/image.js +30 -0
  30. package/dist/esm/src/renders/image.js.map +1 -0
  31. package/dist/esm/src/renders/text.js +82 -0
  32. package/dist/esm/src/renders/text.js.map +1 -0
  33. package/dist/esm/src/types.js +2 -0
  34. package/dist/esm/src/types.js.map +1 -0
  35. package/dist/types/__tests__/assets/templates/index.d.ts +132 -0
  36. package/dist/types/src/builtInRenderer.d.ts +3 -0
  37. package/dist/types/src/pdfUtils.d.ts +19 -0
  38. package/dist/types/src/renderUtils.d.ts +16 -0
  39. package/dist/types/src/renders/barcodes.d.ts +2 -0
  40. package/dist/types/src/renders/image.d.ts +2 -0
  41. package/dist/types/src/renders/text.d.ts +2 -0
  42. package/dist/types/src/types.d.ts +36 -0
  43. package/package.json +2 -7
  44. package/src/builtInRenderer.ts +14 -0
  45. package/src/generate.ts +28 -46
  46. package/src/pdfUtils.ts +76 -0
  47. package/src/renderUtils.ts +68 -0
  48. package/src/renders/barcodes.ts +32 -0
  49. package/src/renders/image.ts +24 -0
  50. package/src/renders/text.ts +114 -0
  51. package/src/types.ts +23 -0
  52. package/dist/cjs/__tests__/helper.test.js +0 -53
  53. package/dist/cjs/__tests__/helper.test.js.map +0 -1
  54. package/dist/cjs/src/helper.js +0 -263
  55. package/dist/cjs/src/helper.js.map +0 -1
  56. package/dist/esm/__tests__/helper.test.js +0 -48
  57. package/dist/esm/__tests__/helper.test.js.map +0 -1
  58. package/dist/esm/src/helper.js +0 -252
  59. package/dist/esm/src/helper.js.map +0 -1
  60. package/dist/types/__tests__/helper.test.d.ts +0 -1
  61. package/dist/types/src/helper.d.ts +0 -67
  62. package/src/helper.ts +0 -391
package/src/helper.ts DELETED
@@ -1,391 +0,0 @@
1
- import {
2
- PDFPage,
3
- PDFFont,
4
- PDFDocument,
5
- PDFImage,
6
- PDFEmbeddedPage,
7
- rgb,
8
- degrees,
9
- setCharacterSpacing,
10
- TransformationMatrix,
11
- } from '@pdfme/pdf-lib';
12
- import bwipjs, { ToBufferOptions } from 'bwip-js';
13
- import {
14
- getB64BasePdf,
15
- b64toUint8Array,
16
- validateBarcodeInput,
17
- Schema,
18
- TextSchema,
19
- isTextSchema,
20
- ImageSchema,
21
- isImageSchema,
22
- BarcodeSchema,
23
- isBarcodeSchema,
24
- Font,
25
- BasePdf,
26
- BarCodeType,
27
- Alignment,
28
- DEFAULT_ALIGNMENT,
29
- DEFAULT_CHARACTER_SPACING,
30
- DEFAULT_FONT_COLOR,
31
- DEFAULT_FONT_SIZE,
32
- DEFAULT_LINE_HEIGHT,
33
- DEFAULT_VERTICAL_ALIGNMENT,
34
- VERTICAL_ALIGN_TOP,
35
- VERTICAL_ALIGN_MIDDLE,
36
- VERTICAL_ALIGN_BOTTOM,
37
- calculateDynamicFontSize,
38
- heightOfFontAtSize,
39
- getFontDescentInPt,
40
- getFontKitFont,
41
- getSplittedLines,
42
- mm2pt,
43
- widthOfTextAtSize,
44
- FontWidthCalcValues,
45
- } from '@pdfme/common';
46
- import { Buffer } from 'buffer';
47
-
48
- export interface InputImageCache {
49
- [key: string]: PDFImage | undefined;
50
- }
51
-
52
- const barCodeType2Bcid = (type: BarCodeType) => (type === 'nw7' ? 'rationalizedCodabar' : type);
53
- export const createBarCode = async (arg: {
54
- type: BarCodeType;
55
- input: string;
56
- width: number;
57
- height: number;
58
- backgroundColor?: string;
59
- }): Promise<Buffer> => {
60
- const { type, input, width, height, backgroundColor } = arg;
61
- const bcid = barCodeType2Bcid(type);
62
- const includetext = true;
63
- const scale = 5;
64
- const bwipjsArg: ToBufferOptions = { bcid, text: input, width, height, scale, includetext };
65
-
66
- if (backgroundColor) {
67
- bwipjsArg.backgroundcolor = backgroundColor;
68
- }
69
-
70
- let res: Buffer;
71
-
72
- if (typeof window !== 'undefined') {
73
- const canvas = document.createElement('canvas');
74
- bwipjs.toCanvas(canvas, bwipjsArg);
75
- const dataUrl = canvas.toDataURL('image/png');
76
- res = b64toUint8Array(dataUrl).buffer as Buffer;
77
- } else {
78
- res = await bwipjs.toBuffer(bwipjsArg);
79
- }
80
-
81
- return res;
82
- };
83
-
84
- type EmbedPdfBox = {
85
- mediaBox: { x: number; y: number; width: number; height: number };
86
- bleedBox: { x: number; y: number; width: number; height: number };
87
- trimBox: { x: number; y: number; width: number; height: number };
88
- };
89
-
90
- export const embedAndGetFontObj = async (arg: { pdfDoc: PDFDocument; font: Font }) => {
91
- const { pdfDoc, font } = arg;
92
- const fontValues = await Promise.all(
93
- Object.values(font).map(async (v) => {
94
- let fontData = v.data;
95
- if (typeof fontData === 'string' && fontData.startsWith('http')) {
96
- fontData = await fetch(fontData).then((res) => res.arrayBuffer());
97
- }
98
- return pdfDoc.embedFont(fontData, {
99
- subset: typeof v.subset === 'undefined' ? true : v.subset,
100
- });
101
- })
102
- );
103
-
104
- return Object.keys(font).reduce(
105
- (acc, cur, i) => Object.assign(acc, { [cur]: fontValues[i] }),
106
- {} as { [key: string]: PDFFont }
107
- );
108
- };
109
-
110
- export const getEmbeddedPagesAndEmbedPdfBoxes = async (arg: {
111
- pdfDoc: PDFDocument;
112
- basePdf: BasePdf;
113
- }) => {
114
- const { pdfDoc, basePdf } = arg;
115
- let embeddedPages: PDFEmbeddedPage[] = [];
116
- let embedPdfBoxes: EmbedPdfBox[] = [];
117
- const willLoadPdf = typeof basePdf === 'string' ? await getB64BasePdf(basePdf) : basePdf;
118
- const embedPdf = await PDFDocument.load(willLoadPdf);
119
- const embedPdfPages = embedPdf.getPages();
120
-
121
- embedPdfBoxes = embedPdfPages.map((p) => ({
122
- mediaBox: p.getMediaBox(),
123
- bleedBox: p.getBleedBox(),
124
- trimBox: p.getTrimBox(),
125
- }));
126
-
127
- const boundingBoxes = embedPdfPages.map((p) => {
128
- const { x, y, width, height } = p.getMediaBox();
129
-
130
- return { left: x, bottom: y, right: width, top: height + y };
131
- });
132
-
133
- const transformationMatrices = embedPdfPages.map(
134
- () => [1, 0, 0, 1, 0, 0] as TransformationMatrix
135
- );
136
-
137
- embeddedPages = await pdfDoc.embedPages(embedPdfPages, boundingBoxes, transformationMatrices);
138
-
139
- return { embeddedPages, embedPdfBoxes };
140
- };
141
-
142
- const convertSchemaDimensionsToPt = (schema: Schema) => {
143
- const width = mm2pt(schema.width);
144
- const height = mm2pt(schema.height);
145
- const rotate = degrees(schema.rotate ? schema.rotate : 0);
146
-
147
- return { width, height, rotate };
148
- };
149
-
150
- const hex2rgb = (hex: string) => {
151
- if (hex.slice(0, 1) === '#') hex = hex.slice(1);
152
- if (hex.length === 3)
153
- hex =
154
- hex.slice(0, 1) +
155
- hex.slice(0, 1) +
156
- hex.slice(1, 2) +
157
- hex.slice(1, 2) +
158
- hex.slice(2, 3) +
159
- hex.slice(2, 3);
160
-
161
- return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)].map((str) => parseInt(str, 16));
162
- };
163
-
164
- const hex2RgbColor = (hexString: string | undefined) => {
165
- if (hexString) {
166
- const [r, g, b] = hex2rgb(hexString);
167
-
168
- return rgb(r / 255, g / 255, b / 255);
169
- }
170
-
171
- // eslint-disable-next-line no-undefined
172
- return undefined;
173
- };
174
-
175
- const getFontProp = async ({ input, font, schema }: { input: string, font: Font, schema: TextSchema }) => {
176
- const fontSize = schema.dynamicFontSize ? await calculateDynamicFontSize({ textSchema: schema, font, input }) : schema.fontSize ?? DEFAULT_FONT_SIZE;
177
- const color = hex2RgbColor(schema.fontColor ?? DEFAULT_FONT_COLOR);
178
- const alignment = schema.alignment ?? DEFAULT_ALIGNMENT;
179
- const verticalAlignment = schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT;
180
- const lineHeight = schema.lineHeight ?? DEFAULT_LINE_HEIGHT;
181
- const characterSpacing = schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING;
182
-
183
- return { fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing };
184
- };
185
-
186
- const calcX = (x: number, alignment: Alignment, boxWidth: number, textWidth: number) => {
187
- let addition = 0;
188
- if (alignment === 'center') {
189
- addition = (boxWidth - textWidth) / 2;
190
- } else if (alignment === 'right') {
191
- addition = boxWidth - textWidth;
192
- }
193
-
194
- return mm2pt(x) + addition;
195
- };
196
-
197
- const calcY = (y: number, pageHeight: number, itemHeight: number) => pageHeight - mm2pt(y) - itemHeight;
198
-
199
- const drawBackgroundColor = (arg: {
200
- templateSchema: TextSchema;
201
- page: PDFPage;
202
- pageHeight: number;
203
- }) => {
204
- const { templateSchema, page, pageHeight } = arg;
205
- if (!templateSchema.backgroundColor) return;
206
- const { width, height } = convertSchemaDimensionsToPt(templateSchema);
207
- const color = hex2RgbColor(templateSchema.backgroundColor);
208
- page.drawRectangle({
209
- x: calcX(templateSchema.position.x, 'left', width, width),
210
- y: calcY(templateSchema.position.y, pageHeight, height),
211
- width,
212
- height,
213
- color,
214
- });
215
- };
216
-
217
- interface FontSetting {
218
- font: Font;
219
- pdfFontObj: {
220
- [key: string]: PDFFont;
221
- };
222
- fallbackFontName: string;
223
- }
224
-
225
- const drawInputByTextSchema = async (arg: {
226
- input: string;
227
- templateSchema: TextSchema;
228
- pdfDoc: PDFDocument;
229
- page: PDFPage;
230
- fontSetting: FontSetting;
231
- }) => {
232
- const { input, templateSchema, page, fontSetting } = arg;
233
- const { font, pdfFontObj, fallbackFontName } = fontSetting;
234
-
235
- const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName];
236
- const fontKitFont = await getFontKitFont(templateSchema, font);
237
-
238
- const pageHeight = page.getHeight();
239
- drawBackgroundColor({ templateSchema, page, pageHeight });
240
-
241
- const { width, height, rotate } = convertSchemaDimensionsToPt(templateSchema);
242
- const { fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing } =
243
- await getFontProp({
244
- input,
245
- font,
246
- schema: templateSchema,
247
- });
248
-
249
- page.pushOperators(setCharacterSpacing(characterSpacing));
250
-
251
- const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
252
- const descent = getFontDescentInPt(fontKitFont, fontSize);
253
- const halfLineHeightAdjustment = lineHeight === 0 ? 0 : ((lineHeight - 1) * fontSize) / 2;
254
-
255
- const fontWidthCalcValues: FontWidthCalcValues = {
256
- font: fontKitFont,
257
- fontSize,
258
- characterSpacing,
259
- boxWidthInPt: width,
260
- };
261
-
262
- let lines: string[] = [];
263
- input.split(/\r|\n|\r\n/g).forEach((inputLine) => {
264
- lines = lines.concat(getSplittedLines(inputLine, fontWidthCalcValues));
265
- });
266
-
267
- // Text lines are rendered from the bottom upwards, we need to adjust the position down
268
- let yOffset = 0;
269
- if (verticalAlignment === VERTICAL_ALIGN_TOP) {
270
- yOffset = firstLineTextHeight + halfLineHeightAdjustment;
271
- } else {
272
- const otherLinesHeight = lineHeight * fontSize * (lines.length - 1);
273
-
274
- if (verticalAlignment === VERTICAL_ALIGN_BOTTOM) {
275
- yOffset = height - otherLinesHeight + descent - halfLineHeightAdjustment;
276
- } else if (verticalAlignment === VERTICAL_ALIGN_MIDDLE) {
277
- yOffset = (height - otherLinesHeight - firstLineTextHeight + descent) / 2 + firstLineTextHeight;
278
- }
279
- }
280
-
281
- lines.forEach((line, rowIndex) => {
282
- const textWidth = widthOfTextAtSize(line, fontKitFont, fontSize, characterSpacing);
283
- const rowYOffset = lineHeight * fontSize * rowIndex;
284
-
285
- page.drawText(line, {
286
- x: calcX(templateSchema.position.x, alignment, width, textWidth),
287
- y: calcY(templateSchema.position.y, pageHeight, yOffset) - rowYOffset,
288
- rotate,
289
- size: fontSize,
290
- color,
291
- lineHeight: lineHeight * fontSize,
292
- maxWidth: width,
293
- font: pdfFontValue,
294
- wordBreaks: [''],
295
- });
296
- });
297
- };
298
-
299
- const getCacheKey = (templateSchema: Schema, input: string) => `${templateSchema.type}${input}`;
300
-
301
- const drawInputByImageSchema = async (arg: {
302
- input: string;
303
- templateSchema: ImageSchema;
304
- pdfDoc: PDFDocument;
305
- page: PDFPage;
306
- inputImageCache: InputImageCache;
307
- }) => {
308
- const { input, templateSchema, pdfDoc, page, inputImageCache } = arg;
309
-
310
- const { width, height, rotate } = convertSchemaDimensionsToPt(templateSchema);
311
- const opt = {
312
- x: calcX(templateSchema.position.x, 'left', width, width),
313
- y: calcY(templateSchema.position.y, page.getHeight(), height),
314
- rotate,
315
- width,
316
- height,
317
- };
318
- const inputImageCacheKey = getCacheKey(templateSchema, input);
319
- let image = inputImageCache[inputImageCacheKey];
320
- if (!image) {
321
- const isPng = input.startsWith('data:image/png;');
322
- image = await (isPng ? pdfDoc.embedPng(input) : pdfDoc.embedJpg(input));
323
- }
324
- inputImageCache[inputImageCacheKey] = image;
325
- page.drawImage(image, opt);
326
- };
327
-
328
- const drawInputByBarcodeSchema = async (arg: {
329
- input: string;
330
- templateSchema: BarcodeSchema;
331
- pdfDoc: PDFDocument;
332
- page: PDFPage;
333
- inputImageCache: InputImageCache;
334
- }) => {
335
- const { input, templateSchema, pdfDoc, page, inputImageCache } = arg;
336
- if (!validateBarcodeInput(templateSchema.type as BarCodeType, input)) return;
337
-
338
- const { width, height, rotate } = convertSchemaDimensionsToPt(templateSchema);
339
- const opt = {
340
- x: calcX(templateSchema.position.x, 'left', width, width),
341
- y: calcY(templateSchema.position.y, page.getHeight(), height),
342
- rotate,
343
- width,
344
- height,
345
- };
346
- const inputBarcodeCacheKey = getCacheKey(templateSchema, input);
347
- let image = inputImageCache[inputBarcodeCacheKey];
348
- if (!image) {
349
- const imageBuf = await createBarCode(
350
- Object.assign(templateSchema, { type: templateSchema.type as BarCodeType, input })
351
- );
352
- image = await pdfDoc.embedPng(imageBuf);
353
- }
354
- inputImageCache[inputBarcodeCacheKey] = image;
355
- page.drawImage(image, opt);
356
- };
357
-
358
- export const drawInputByTemplateSchema = async (arg: {
359
- input: string;
360
- templateSchema: Schema;
361
- pdfDoc: PDFDocument;
362
- page: PDFPage;
363
- fontSetting: FontSetting;
364
- inputImageCache: InputImageCache;
365
- }) => {
366
- if (!arg.input || !arg.templateSchema) return;
367
-
368
- if (isTextSchema(arg.templateSchema)) {
369
- const templateSchema = arg.templateSchema as TextSchema;
370
- await drawInputByTextSchema({ ...arg, templateSchema });
371
- } else if (isImageSchema(arg.templateSchema)) {
372
- const templateSchema = arg.templateSchema as ImageSchema;
373
- await drawInputByImageSchema({ ...arg, templateSchema });
374
- } else if (isBarcodeSchema(arg.templateSchema)) {
375
- const templateSchema = arg.templateSchema as BarcodeSchema;
376
- await drawInputByBarcodeSchema({ ...arg, templateSchema });
377
- }
378
- };
379
-
380
- export const drawEmbeddedPage = (arg: {
381
- page: PDFPage;
382
- embeddedPage: PDFEmbeddedPage;
383
- embedPdfBox: EmbedPdfBox;
384
- }) => {
385
- const { page, embeddedPage, embedPdfBox } = arg;
386
- page.drawPage(embeddedPage);
387
- const { mediaBox: mb, bleedBox: bb, trimBox: tb } = embedPdfBox;
388
- page.setMediaBox(mb.x, mb.y, mb.width, mb.height);
389
- page.setBleedBox(bb.x, bb.y, bb.width, bb.height);
390
- page.setTrimBox(tb.x, tb.y, tb.width, tb.height);
391
- };