@pdfme/common 1.1.9 → 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.
Files changed (40) hide show
  1. package/dist/cjs/__tests__/calculateDynamicFontSize.test.js +97 -0
  2. package/dist/cjs/__tests__/calculateDynamicFontSize.test.js.map +1 -0
  3. package/dist/cjs/src/calculateDynamicFontSize.js +103 -0
  4. package/dist/cjs/src/calculateDynamicFontSize.js.map +1 -0
  5. package/dist/cjs/src/constants.js +6 -2
  6. package/dist/cjs/src/constants.js.map +1 -1
  7. package/dist/cjs/src/helper.js +3 -10
  8. package/dist/cjs/src/helper.js.map +1 -1
  9. package/dist/cjs/src/index.js +8 -2
  10. package/dist/cjs/src/index.js.map +1 -1
  11. package/dist/cjs/src/schema.js +11 -6
  12. package/dist/cjs/src/schema.js.map +1 -1
  13. package/dist/cjs/src/type.js.map +1 -1
  14. package/dist/esm/__tests__/calculateDynamicFontSize.test.js +72 -0
  15. package/dist/esm/__tests__/calculateDynamicFontSize.test.js.map +1 -0
  16. package/dist/esm/src/calculateDynamicFontSize.js +76 -0
  17. package/dist/esm/src/calculateDynamicFontSize.js.map +1 -0
  18. package/dist/esm/src/constants.js +5 -1
  19. package/dist/esm/src/constants.js.map +1 -1
  20. package/dist/esm/src/helper.js +4 -11
  21. package/dist/esm/src/helper.js.map +1 -1
  22. package/dist/esm/src/index.js +3 -2
  23. package/dist/esm/src/index.js.map +1 -1
  24. package/dist/esm/src/schema.js +10 -5
  25. package/dist/esm/src/schema.js.map +1 -1
  26. package/dist/esm/src/type.js.map +1 -1
  27. package/dist/types/__tests__/calculateDynamicFontSize.test.d.ts +1 -0
  28. package/dist/types/src/calculateDynamicFontSize.d.ts +6 -0
  29. package/dist/types/src/constants.d.ts +5 -1
  30. package/dist/types/src/index.d.ts +5 -4
  31. package/dist/types/src/schema.d.ts +386 -43
  32. package/dist/types/src/type.d.ts +6 -1
  33. package/package.json +7 -2
  34. package/src/calculateDynamicFontSize.ts +101 -0
  35. package/src/constants.ts +6 -2
  36. package/src/helper.ts +4 -11
  37. package/src/index.ts +14 -2
  38. package/src/schema.ts +12 -5
  39. package/src/type.ts +2 -0
  40. package/tsconfig.json +6 -0
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { Lang, Size, Alignment, BarcodeSchemaType, SchemaType, CommonSchema as _CommonSchema, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, PreviewReactProps, DesignerProps, DesignerReactProps } from './schema.js';
2
+ import { Lang, Size, Alignment, BarcodeSchemaType, SchemaType, CommonSchema as _CommonSchema, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaInputs, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, PreviewReactProps, DesignerProps, DesignerReactProps } from './schema.js';
3
3
  declare type CommonSchema = z.infer<typeof _CommonSchema>;
4
4
  export declare const schemaTypes: readonly ["text", "image", "qrcode", "japanpost", "ean13", "ean8", "code39", "code128", "nw7", "itf14", "upca", "upce"];
5
5
  export declare const isTextSchema: (arg: CommonSchema) => arg is {
@@ -11,6 +11,10 @@ export declare const isTextSchema: (arg: CommonSchema) => arg is {
11
11
  fontName?: string | undefined;
12
12
  fontColor?: string | undefined;
13
13
  characterSpacing?: number | undefined;
14
+ dynamicFontSize?: {
15
+ max: number;
16
+ min: number;
17
+ } | undefined;
14
18
  type: "text";
15
19
  height: number;
16
20
  width: number;
@@ -48,6 +52,7 @@ export declare type TextSchema = z.infer<typeof TextSchema>;
48
52
  export declare type ImageSchema = z.infer<typeof ImageSchema>;
49
53
  export declare type BarcodeSchema = z.infer<typeof BarcodeSchema>;
50
54
  export declare type Schema = z.infer<typeof Schema>;
55
+ export declare type SchemaInputs = z.infer<typeof SchemaInputs>;
51
56
  export declare type SchemaForUI = z.infer<typeof SchemaForUI>;
52
57
  export declare type Font = z.infer<typeof Font>;
53
58
  export declare type BasePdf = z.infer<typeof BasePdf>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/common",
3
- "version": "1.1.9",
3
+ "version": "1.2.0",
4
4
  "sideEffects": false,
5
5
  "author": "hand-dot",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "node": ">=14"
35
35
  },
36
36
  "scripts": {
37
- "develop": "tsc -w",
37
+ "develop": "tsc -p tsconfig.esm.json -w",
38
38
  "build": "npm run build:cjs && npm run build:esm",
39
39
  "build:cjs": "tsc -p tsconfig.cjs.json",
40
40
  "build:esm": "tsc -p tsconfig.esm.json",
@@ -46,6 +46,8 @@
46
46
  "prune": "ts-prune src"
47
47
  },
48
48
  "dependencies": {
49
+ "buffer": "^6.0.3",
50
+ "fontkit": "^2.0.2",
49
51
  "zod": "^3.20.2"
50
52
  },
51
53
  "jest": {
@@ -68,5 +70,8 @@
68
70
  },
69
71
  "publishConfig": {
70
72
  "access": "public"
73
+ },
74
+ "devDependencies": {
75
+ "@types/fontkit": "^2.0.3"
71
76
  }
72
77
  }
@@ -0,0 +1,101 @@
1
+ import * as fontkit from 'fontkit';
2
+ import { TextSchema, Font } from './type';
3
+ import { Buffer } from 'buffer';
4
+ import {
5
+ DEFAULT_FONT_VALUE,
6
+ DEFAULT_FONT_NAME,
7
+ DEFAULT_FONT_SIZE,
8
+ DEFAULT_CHARACTER_SPACING,
9
+ DEFAULT_TOLERANCE,
10
+ DEFAULT_FONT_SIZE_ADJUSTMENT,
11
+ DEFAULT_PT_TO_MM_RATIO
12
+ } from './constants';
13
+ import { b64toUint8Array } from "."
14
+
15
+ const widthOfTextAtSize = (input: string, fontKitFont: fontkit.Font, fontSize: number) => {
16
+ const { glyphs } = fontKitFont.layout(input);
17
+ const scale = 1000 / fontKitFont.unitsPerEm;
18
+ return glyphs.reduce((totalWidth, glyph) => totalWidth + glyph.advanceWidth * scale, 0) * (fontSize / 1000);
19
+ }
20
+
21
+ const calculateCharacterSpacing = (
22
+ textContent: string,
23
+ textCharacterSpacing: number
24
+ ) => {
25
+ const numberOfCharacters = textContent.length;
26
+ return (numberOfCharacters - 1) * textCharacterSpacing;
27
+ };
28
+
29
+ const calculateTextWidthInMm = (textContent: string, textWidth: number, textCharacterSpacing: number) =>
30
+ (textWidth + calculateCharacterSpacing(textContent, textCharacterSpacing)) * DEFAULT_PT_TO_MM_RATIO;
31
+
32
+ const getLongestLine = (
33
+ textContentRows: string[],
34
+ fontKitFont: fontkit.Font,
35
+ fontSize: number,
36
+ characterSpacingCount: number
37
+ ) => {
38
+ let longestLine = '';
39
+ let maxLineWidth = 0;
40
+
41
+ textContentRows.forEach((line) => {
42
+ const textWidth = widthOfTextAtSize(line, fontKitFont, fontSize);
43
+ const lineWidth = calculateTextWidthInMm(line, textWidth, characterSpacingCount);
44
+
45
+ if (lineWidth > maxLineWidth) {
46
+ longestLine = line;
47
+ maxLineWidth = lineWidth;
48
+ }
49
+ });
50
+
51
+ return longestLine;
52
+ };
53
+
54
+
55
+ const fontKitFontCache: { [fontName: string]: fontkit.Font } = {};
56
+ const createFontKitFont = async (font: Font, fontName: string = DEFAULT_FONT_NAME) => {
57
+ if (fontKitFontCache[fontName]) {
58
+ return fontKitFontCache[fontName];
59
+ }
60
+
61
+ let fontData = font[fontName]?.data || DEFAULT_FONT_VALUE;
62
+ if (typeof fontData === 'string') {
63
+ fontData = fontData.startsWith('http') ? await fetch(fontData).then((res) => res.arrayBuffer()) : b64toUint8Array(fontData);
64
+ }
65
+
66
+ const fontKitFont = fontkit.create(fontData instanceof Buffer ? fontData : Buffer.from(fontData as string));
67
+ fontKitFontCache[fontName] = fontKitFont
68
+
69
+ return fontKitFont;
70
+ }
71
+
72
+ const getTextContent = (input: string, fontKitFont: fontkit.Font, fontSize: number, characterSpacingCount: number): string => {
73
+ const textContentRows = input.split('\n');
74
+ return textContentRows.length > 1 ? getLongestLine(textContentRows, fontKitFont, fontSize, characterSpacingCount) : input;
75
+ }
76
+
77
+ export const calculateDynamicFontSize = async ({ textSchema, font, input }: { textSchema: TextSchema, font: Font, input: string }) => {
78
+ const { fontName, fontSize: _fontSize, dynamicFontSize: dynamicFontSizeSetting, characterSpacing, width } = textSchema;
79
+ const fontSize = _fontSize || DEFAULT_FONT_SIZE;
80
+ if (!dynamicFontSizeSetting) return fontSize;
81
+
82
+ const characterSpacingCount = characterSpacing ?? DEFAULT_CHARACTER_SPACING;
83
+ const fontKitFont = await createFontKitFont(font, fontName);
84
+ const textContent = getTextContent(input, fontKitFont, fontSize, characterSpacingCount);
85
+ const textWidth = widthOfTextAtSize(textContent, fontKitFont, fontSize);
86
+
87
+ let dynamicFontSize = fontSize;
88
+ let textWidthInMm = calculateTextWidthInMm(textContent, textWidth, characterSpacingCount);
89
+
90
+ while (textWidthInMm > width - DEFAULT_TOLERANCE && dynamicFontSize > dynamicFontSizeSetting.min) {
91
+ dynamicFontSize -= DEFAULT_FONT_SIZE_ADJUSTMENT;
92
+ textWidthInMm = calculateTextWidthInMm(textContent, widthOfTextAtSize(textContent, fontKitFont, dynamicFontSize), characterSpacingCount);
93
+ }
94
+
95
+ while (textWidthInMm < width - DEFAULT_TOLERANCE && dynamicFontSize < dynamicFontSizeSetting.max) {
96
+ dynamicFontSize += DEFAULT_FONT_SIZE_ADJUSTMENT;
97
+ textWidthInMm = calculateTextWidthInMm(textContent, widthOfTextAtSize(textContent, fontKitFont, dynamicFontSize), characterSpacingCount);
98
+ }
99
+
100
+ return dynamicFontSize;
101
+ };