@pdfme/generator 1.1.10 → 1.2.0
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/cjs/__tests__/generate.test.js +96 -83
- package/dist/cjs/__tests__/generate.test.js.map +1 -1
- package/dist/cjs/src/generate.js +7 -8
- package/dist/cjs/src/generate.js.map +1 -1
- package/dist/cjs/src/helper.js +29 -43
- package/dist/cjs/src/helper.js.map +1 -1
- package/dist/cjs/src/index.js +2 -2
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/esm/__tests__/generate.test.js +96 -83
- package/dist/esm/__tests__/generate.test.js.map +1 -1
- package/dist/esm/src/generate.js +8 -9
- package/dist/esm/src/generate.js.map +1 -1
- package/dist/esm/src/helper.js +30 -44
- package/dist/esm/src/helper.js.map +1 -1
- package/dist/esm/src/index.js +2 -2
- package/dist/esm/src/index.js.map +1 -1
- package/dist/types/__tests__/assets/templates/index.d.ts +156 -0
- package/dist/types/src/helper.d.ts +4 -4
- package/dist/types/src/index.d.ts +2 -2
- package/package.json +2 -2
- package/src/generate.ts +21 -16
- package/src/helper.ts +37 -46
- package/src/index.ts +2 -2
- package/tsconfig.json +6 -0
package/src/helper.ts
CHANGED
@@ -30,6 +30,7 @@ import {
|
|
30
30
|
DEFAULT_LINE_HEIGHT,
|
31
31
|
DEFAULT_CHARACTER_SPACING,
|
32
32
|
DEFAULT_FONT_COLOR,
|
33
|
+
calculateDynamicFontSize,
|
33
34
|
} from '@pdfme/common';
|
34
35
|
|
35
36
|
export interface InputImageCache {
|
@@ -166,8 +167,8 @@ const hex2RgbColor = (hexString: string | undefined) => {
|
|
166
167
|
return undefined;
|
167
168
|
};
|
168
169
|
|
169
|
-
const getFontProp = (schema: TextSchema) => {
|
170
|
-
const size = schema.fontSize ?? DEFAULT_FONT_SIZE;
|
170
|
+
const getFontProp = async ({ input, font, schema }: { input: string, font: Font, schema: TextSchema }) => {
|
171
|
+
const size = schema.dynamicFontSize ? await calculateDynamicFontSize({ textSchema: schema, font, input }) : schema.fontSize ?? DEFAULT_FONT_SIZE;
|
171
172
|
const color = hex2RgbColor(schema.fontColor ?? DEFAULT_FONT_COLOR);
|
172
173
|
const alignment = schema.alignment ?? DEFAULT_ALIGNMENT;
|
173
174
|
const lineHeight = schema.lineHeight ?? DEFAULT_LINE_HEIGHT;
|
@@ -208,15 +209,15 @@ const drawBackgroundColor = (arg: {
|
|
208
209
|
};
|
209
210
|
|
210
211
|
type IsOverEval = (testString: string) => boolean;
|
212
|
+
|
211
213
|
/**
|
212
|
-
* Incrementally
|
213
|
-
* and
|
214
|
-
*
|
215
|
-
* return `null` to indicate if inputLine is shorter as the available bbox
|
214
|
+
* Incrementally checks the current line for its real length
|
215
|
+
* and returns the position where it exceeds the box width.
|
216
|
+
* Returns `null` to indicate if inputLine is shorter as the available bbox.
|
216
217
|
*/
|
217
218
|
const getOverPosition = (inputLine: string, isOverEval: IsOverEval) => {
|
218
|
-
for (let i = 0; i <= inputLine.length; i
|
219
|
-
if (isOverEval(inputLine.
|
219
|
+
for (let i = 0; i <= inputLine.length; i++) {
|
220
|
+
if (isOverEval(inputLine.slice(0, i))) {
|
220
221
|
return i;
|
221
222
|
}
|
222
223
|
}
|
@@ -225,69 +226,64 @@ const getOverPosition = (inputLine: string, isOverEval: IsOverEval) => {
|
|
225
226
|
};
|
226
227
|
|
227
228
|
/**
|
228
|
-
*
|
229
|
+
* Gets the position of the split. Splits the exceeding line at
|
229
230
|
* the last whitespace over it exceeds the bounding box width.
|
230
231
|
*/
|
231
232
|
const getSplitPosition = (inputLine: string, isOverEval: IsOverEval) => {
|
232
233
|
const overPos = getOverPosition(inputLine, isOverEval);
|
233
|
-
|
234
|
-
|
235
|
-
*/
|
236
|
-
if (overPos === null) return inputLine.length;
|
234
|
+
if (overPos === null) return inputLine.length; // input line is shorter than the available space
|
235
|
+
|
237
236
|
let overPosTmp = overPos;
|
238
|
-
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0)
|
239
|
-
|
240
|
-
|
241
|
-
* split one char over so we do not overfill the box
|
242
|
-
*/
|
237
|
+
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) {
|
238
|
+
overPosTmp--;
|
239
|
+
}
|
243
240
|
|
241
|
+
// For very long lines with no whitespace use the original overPos
|
244
242
|
return overPosTmp > 0 ? overPosTmp : overPos - 1;
|
245
243
|
};
|
246
244
|
|
247
245
|
/**
|
248
|
-
*
|
246
|
+
* Recursively splits the line at getSplitPosition.
|
249
247
|
* If there is some leftover, split the rest again in the same manner.
|
250
248
|
*/
|
251
249
|
const getSplittedLines = (inputLine: string, isOverEval: IsOverEval): string[] => {
|
252
250
|
const splitPos = getSplitPosition(inputLine, isOverEval);
|
253
|
-
const splittedLine = inputLine.
|
254
|
-
const rest = inputLine.
|
255
|
-
|
256
|
-
|
257
|
-
* so we can join them over the recursion
|
258
|
-
*/
|
259
|
-
if (rest.length === 0) {
|
251
|
+
const splittedLine = inputLine.substring(0, splitPos);
|
252
|
+
const rest = inputLine.substring(splitPos).trimStart();
|
253
|
+
|
254
|
+
if (rest.length === 0) { // end recursion if there is no rest
|
260
255
|
return [splittedLine];
|
261
256
|
}
|
262
257
|
|
263
258
|
return [splittedLine, ...getSplittedLines(rest, isOverEval)];
|
264
259
|
};
|
265
260
|
|
266
|
-
interface
|
267
|
-
|
261
|
+
interface FontSetting {
|
262
|
+
font: Font;
|
263
|
+
pdfFontObj: {
|
268
264
|
[key: string]: PDFFont;
|
269
265
|
};
|
270
266
|
fallbackFontName: string;
|
271
|
-
splitThreshold: number;
|
272
267
|
}
|
273
268
|
|
274
|
-
const drawInputByTextSchema = (arg: {
|
269
|
+
const drawInputByTextSchema = async (arg: {
|
275
270
|
input: string;
|
276
271
|
templateSchema: TextSchema;
|
277
272
|
pdfDoc: PDFDocument;
|
278
273
|
page: PDFPage;
|
279
274
|
pageHeight: number;
|
280
|
-
|
275
|
+
fontSetting: FontSetting;
|
281
276
|
}) => {
|
282
|
-
const { input, templateSchema, page, pageHeight,
|
283
|
-
const {
|
277
|
+
const { input, templateSchema, page, pageHeight, fontSetting } = arg;
|
278
|
+
const { font, pdfFontObj, fallbackFontName } = fontSetting;
|
284
279
|
|
285
|
-
const
|
280
|
+
const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName];
|
286
281
|
|
287
282
|
drawBackgroundColor({ templateSchema, page, pageHeight });
|
288
283
|
|
289
284
|
const { width, rotate } = getSchemaSizeAndRotate(templateSchema);
|
290
|
-
const { size, color, alignment, lineHeight, characterSpacing } = getFontProp(templateSchema);
|
285
|
+
const { size, color, alignment, lineHeight, characterSpacing } = await getFontProp({ input, font, schema: templateSchema });
|
286
|
+
|
291
287
|
page.pushOperators(setCharacterSpacing(characterSpacing));
|
292
288
|
|
293
289
|
let beforeLineOver = 0;
|
@@ -295,18 +291,13 @@ const drawInputByTextSchema = (arg: {
|
|
295
291
|
input.split(/\r|\n|\r\n/g).forEach((inputLine, inputLineIndex) => {
|
296
292
|
const isOverEval = (testString: string) => {
|
297
293
|
const testStringWidth =
|
298
|
-
|
299
|
-
|
300
|
-
* split if the difference is less then two pixel
|
301
|
-
* (found out / tested this threshold heuristically, most probably widthOfTextAtSize is unprecise)
|
302
|
-
**/
|
303
|
-
|
304
|
-
return width - testStringWidth <= splitThreshold;
|
294
|
+
pdfFontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing;
|
295
|
+
return width <= testStringWidth;
|
305
296
|
};
|
306
297
|
const splitedLines = getSplittedLines(inputLine, isOverEval);
|
307
298
|
const drawLine = (splitedLine: string, splitedLineIndex: number) => {
|
308
299
|
const textWidth =
|
309
|
-
|
300
|
+
pdfFontValue.widthOfTextAtSize(splitedLine, size) +
|
310
301
|
(splitedLine.length - 1) * characterSpacing;
|
311
302
|
page.drawText(splitedLine, {
|
312
303
|
x: calcX(templateSchema.position.x, alignment, width, textWidth),
|
@@ -319,7 +310,7 @@ const drawInputByTextSchema = (arg: {
|
|
319
310
|
color,
|
320
311
|
lineHeight: lineHeight * size,
|
321
312
|
maxWidth: width,
|
322
|
-
font:
|
313
|
+
font: pdfFontValue,
|
323
314
|
wordBreaks: [''],
|
324
315
|
});
|
325
316
|
if (splitedLines.length === splitedLineIndex + 1) beforeLineOver += splitedLineIndex;
|
@@ -396,14 +387,14 @@ export const drawInputByTemplateSchema = async (arg: {
|
|
396
387
|
pdfDoc: PDFDocument;
|
397
388
|
page: PDFPage;
|
398
389
|
pageHeight: number;
|
399
|
-
|
390
|
+
fontSetting: FontSetting;
|
400
391
|
inputImageCache: InputImageCache;
|
401
392
|
}) => {
|
402
393
|
if (!arg.input || !arg.templateSchema) return;
|
403
394
|
|
404
395
|
if (isTextSchema(arg.templateSchema)) {
|
405
396
|
const templateSchema = arg.templateSchema as TextSchema;
|
406
|
-
drawInputByTextSchema({ ...arg, templateSchema });
|
397
|
+
await drawInputByTextSchema({ ...arg, templateSchema });
|
407
398
|
} else if (isImageSchema(arg.templateSchema)) {
|
408
399
|
const templateSchema = arg.templateSchema as ImageSchema;
|
409
400
|
await drawInputByImageSchema({ ...arg, templateSchema });
|
package/src/index.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import generate from './generate.js';
|
2
2
|
import {
|
3
3
|
BLANK_PDF,
|
4
|
-
|
4
|
+
DEFAULT_FONT_VALUE,
|
5
5
|
isTextSchema,
|
6
6
|
isImageSchema,
|
7
7
|
isBarcodeSchema,
|
@@ -38,7 +38,7 @@ import type {
|
|
38
38
|
export {
|
39
39
|
generate,
|
40
40
|
BLANK_PDF,
|
41
|
-
|
41
|
+
DEFAULT_FONT_VALUE,
|
42
42
|
isTextSchema,
|
43
43
|
isImageSchema,
|
44
44
|
isBarcodeSchema,
|