@pdfme/generator 2.0.2 → 2.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/README.md +6 -2
- package/dist/cjs/__tests__/assets/templates/index.js +10 -0
- package/dist/cjs/__tests__/assets/templates/index.js.map +1 -1
- package/dist/cjs/__tests__/generate.test.js +9 -0
- package/dist/cjs/__tests__/generate.test.js.map +1 -1
- package/dist/cjs/src/generate.js +0 -1
- package/dist/cjs/src/generate.js.map +1 -1
- package/dist/cjs/src/helper.js +62 -95
- package/dist/cjs/src/helper.js.map +1 -1
- package/dist/esm/__tests__/assets/templates/index.js +10 -0
- package/dist/esm/__tests__/assets/templates/index.js.map +1 -1
- package/dist/esm/__tests__/generate.test.js +9 -0
- package/dist/esm/__tests__/generate.test.js.map +1 -1
- package/dist/esm/src/generate.js +0 -1
- package/dist/esm/src/generate.js.map +1 -1
- package/dist/esm/src/helper.js +60 -93
- package/dist/esm/src/helper.js.map +1 -1
- package/dist/types/__tests__/assets/templates/index.d.ts +308 -0
- package/dist/types/src/helper.d.ts +0 -1
- package/package.json +2 -2
- package/src/generate.ts +0 -1
- package/src/helper.ts +76 -115
    
        package/package.json
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            {
         | 
| 2 2 | 
             
              "name": "@pdfme/generator",
         | 
| 3 | 
            -
              "version": "2.0 | 
| 3 | 
            +
              "version": "2.2.0",
         | 
| 4 4 | 
             
              "sideEffects": false,
         | 
| 5 5 | 
             
              "author": "hand-dot",
         | 
| 6 6 | 
             
              "license": "MIT",
         | 
| @@ -60,7 +60,7 @@ | |
| 60 60 | 
             
                "pngjs": "^6.0.0"
         | 
| 61 61 | 
             
              },
         | 
| 62 62 | 
             
              "peerDependencies": {
         | 
| 63 | 
            -
                "@pdfme/common": "^2. | 
| 63 | 
            +
                "@pdfme/common": "^2.1.0"
         | 
| 64 64 | 
             
              },
         | 
| 65 65 | 
             
              "jest": {
         | 
| 66 66 | 
             
                "resolver": "ts-jest-resolver",
         | 
    
        package/src/generate.ts
    CHANGED
    
    
    
        package/src/helper.ts
    CHANGED
    
    | @@ -25,14 +25,23 @@ import { | |
| 25 25 | 
             
              BasePdf,
         | 
| 26 26 | 
             
              BarCodeType,
         | 
| 27 27 | 
             
              Alignment,
         | 
| 28 | 
            -
              DEFAULT_FONT_SIZE,
         | 
| 29 28 | 
             
              DEFAULT_ALIGNMENT,
         | 
| 30 | 
            -
              DEFAULT_LINE_HEIGHT,
         | 
| 31 29 | 
             
              DEFAULT_CHARACTER_SPACING,
         | 
| 32 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,
         | 
| 33 37 | 
             
              calculateDynamicFontSize,
         | 
| 34 38 | 
             
              heightOfFontAtSize,
         | 
| 35 | 
            -
               | 
| 39 | 
            +
              getFontDescentInPt,
         | 
| 40 | 
            +
              getFontKitFont,
         | 
| 41 | 
            +
              getSplittedLines,
         | 
| 42 | 
            +
              mm2pt,
         | 
| 43 | 
            +
              widthOfTextAtSize,
         | 
| 44 | 
            +
              FontWidthCalcValues,
         | 
| 36 45 | 
             
            } from '@pdfme/common';
         | 
| 37 46 | 
             
            import { Buffer } from 'buffer';
         | 
| 38 47 |  | 
| @@ -130,14 +139,7 @@ export const getEmbeddedPagesAndEmbedPdfBoxes = async (arg: { | |
| 130 139 | 
             
              return { embeddedPages, embedPdfBoxes };
         | 
| 131 140 | 
             
            };
         | 
| 132 141 |  | 
| 133 | 
            -
            const  | 
| 134 | 
            -
              // https://www.ddc.co.jp/words/archives/20090701114500.html
         | 
| 135 | 
            -
              const ptRatio = 2.8346;
         | 
| 136 | 
            -
             | 
| 137 | 
            -
              return parseFloat(String(mm)) * ptRatio;
         | 
| 138 | 
            -
            };
         | 
| 139 | 
            -
             | 
| 140 | 
            -
            const getSchemaSizeAndRotate = (schema: Schema) => {
         | 
| 142 | 
            +
            const convertSchemaDimensionsToPt = (schema: Schema) => {
         | 
| 141 143 | 
             
              const width = mm2pt(schema.width);
         | 
| 142 144 | 
             
              const height = mm2pt(schema.height);
         | 
| 143 145 | 
             
              const rotate = degrees(schema.rotate ? schema.rotate : 0);
         | 
| @@ -171,13 +173,14 @@ const hex2RgbColor = (hexString: string | undefined) => { | |
| 171 173 | 
             
            };
         | 
| 172 174 |  | 
| 173 175 | 
             
            const getFontProp = async ({ input, font, schema }: { input: string, font: Font, schema: TextSchema }) => {
         | 
| 174 | 
            -
              const  | 
| 176 | 
            +
              const fontSize = schema.dynamicFontSize ? await calculateDynamicFontSize({ textSchema: schema, font, input }) : schema.fontSize ?? DEFAULT_FONT_SIZE;
         | 
| 175 177 | 
             
              const color = hex2RgbColor(schema.fontColor ?? DEFAULT_FONT_COLOR);
         | 
| 176 178 | 
             
              const alignment = schema.alignment ?? DEFAULT_ALIGNMENT;
         | 
| 179 | 
            +
              const verticalAlignment = schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT;
         | 
| 177 180 | 
             
              const lineHeight = schema.lineHeight ?? DEFAULT_LINE_HEIGHT;
         | 
| 178 181 | 
             
              const characterSpacing = schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING;
         | 
| 179 182 |  | 
| 180 | 
            -
              return {  | 
| 183 | 
            +
              return { fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing };
         | 
| 181 184 | 
             
            };
         | 
| 182 185 |  | 
| 183 186 | 
             
            const calcX = (x: number, alignment: Alignment, boxWidth: number, textWidth: number) => {
         | 
| @@ -191,7 +194,7 @@ const calcX = (x: number, alignment: Alignment, boxWidth: number, textWidth: num | |
| 191 194 | 
             
              return mm2pt(x) + addition;
         | 
| 192 195 | 
             
            };
         | 
| 193 196 |  | 
| 194 | 
            -
            const calcY = (y: number,  | 
| 197 | 
            +
            const calcY = (y: number, pageHeight: number, itemHeight: number) => pageHeight - mm2pt(y) - itemHeight;
         | 
| 195 198 |  | 
| 196 199 | 
             
            const drawBackgroundColor = (arg: {
         | 
| 197 200 | 
             
              templateSchema: TextSchema;
         | 
| @@ -200,7 +203,7 @@ const drawBackgroundColor = (arg: { | |
| 200 203 | 
             
            }) => {
         | 
| 201 204 | 
             
              const { templateSchema, page, pageHeight } = arg;
         | 
| 202 205 | 
             
              if (!templateSchema.backgroundColor) return;
         | 
| 203 | 
            -
              const { width, height } =  | 
| 206 | 
            +
              const { width, height } = convertSchemaDimensionsToPt(templateSchema);
         | 
| 204 207 | 
             
              const color = hex2RgbColor(templateSchema.backgroundColor);
         | 
| 205 208 | 
             
              page.drawRectangle({
         | 
| 206 209 | 
             
                x: calcX(templateSchema.position.x, 'left', width, width),
         | 
| @@ -211,57 +214,6 @@ const drawBackgroundColor = (arg: { | |
| 211 214 | 
             
              });
         | 
| 212 215 | 
             
            };
         | 
| 213 216 |  | 
| 214 | 
            -
            type IsOverEval = (testString: string) => boolean;
         | 
| 215 | 
            -
             | 
| 216 | 
            -
            /**
         | 
| 217 | 
            -
             * Incrementally checks the current line for its real length
         | 
| 218 | 
            -
             * and returns the position where it exceeds the box width.
         | 
| 219 | 
            -
             * Returns `null` to indicate if inputLine is shorter as the available bbox.
         | 
| 220 | 
            -
             */
         | 
| 221 | 
            -
            const getOverPosition = (inputLine: string, isOverEval: IsOverEval) => {
         | 
| 222 | 
            -
              for (let i = 0; i <= inputLine.length; i++) {
         | 
| 223 | 
            -
                if (isOverEval(inputLine.slice(0, i))) {
         | 
| 224 | 
            -
                  return i;
         | 
| 225 | 
            -
                }
         | 
| 226 | 
            -
              }
         | 
| 227 | 
            -
             | 
| 228 | 
            -
              return null;
         | 
| 229 | 
            -
            };
         | 
| 230 | 
            -
             | 
| 231 | 
            -
            /**
         | 
| 232 | 
            -
             * Gets the position of the split. Splits the exceeding line at
         | 
| 233 | 
            -
             * the last whitespace over it exceeds the bounding box width.
         | 
| 234 | 
            -
             */
         | 
| 235 | 
            -
            const getSplitPosition = (inputLine: string, isOverEval: IsOverEval) => {
         | 
| 236 | 
            -
              const overPos = getOverPosition(inputLine, isOverEval);
         | 
| 237 | 
            -
              if (overPos === null) return inputLine.length;  // input line is shorter than the available space
         | 
| 238 | 
            -
             | 
| 239 | 
            -
              let overPosTmp = overPos;
         | 
| 240 | 
            -
              while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) {
         | 
| 241 | 
            -
                overPosTmp--;
         | 
| 242 | 
            -
              }
         | 
| 243 | 
            -
             | 
| 244 | 
            -
              // For very long lines with no whitespace use the original overPos
         | 
| 245 | 
            -
              return overPosTmp > 0 ? overPosTmp : overPos - 1;
         | 
| 246 | 
            -
            };
         | 
| 247 | 
            -
             | 
| 248 | 
            -
            /**
         | 
| 249 | 
            -
             * Recursively splits the line at getSplitPosition.
         | 
| 250 | 
            -
             * If there is some leftover, split the rest again in the same manner.
         | 
| 251 | 
            -
             */
         | 
| 252 | 
            -
            const getSplittedLines = (inputLine: string, isOverEval: IsOverEval): string[] => {
         | 
| 253 | 
            -
              const splitPos = getSplitPosition(inputLine, isOverEval);
         | 
| 254 | 
            -
              const splittedLine = inputLine.substring(0, splitPos);
         | 
| 255 | 
            -
              const rest = inputLine.substring(splitPos).trimStart();
         | 
| 256 | 
            -
             | 
| 257 | 
            -
              if (rest.length === 0) {
         | 
| 258 | 
            -
                // end recursion if there is no rest
         | 
| 259 | 
            -
                return [splittedLine];
         | 
| 260 | 
            -
              }
         | 
| 261 | 
            -
             | 
| 262 | 
            -
              return [splittedLine, ...getSplittedLines(rest, isOverEval)];
         | 
| 263 | 
            -
            };
         | 
| 264 | 
            -
             | 
| 265 217 | 
             
            interface FontSetting {
         | 
| 266 218 | 
             
              font: Font;
         | 
| 267 219 | 
             
              pdfFontObj: {
         | 
| @@ -275,60 +227,72 @@ const drawInputByTextSchema = async (arg: { | |
| 275 227 | 
             
              templateSchema: TextSchema;
         | 
| 276 228 | 
             
              pdfDoc: PDFDocument;
         | 
| 277 229 | 
             
              page: PDFPage;
         | 
| 278 | 
            -
              pageHeight: number;
         | 
| 279 230 | 
             
              fontSetting: FontSetting;
         | 
| 280 231 | 
             
            }) => {
         | 
| 281 | 
            -
              const { input, templateSchema, page,  | 
| 232 | 
            +
              const { input, templateSchema, page, fontSetting } = arg;
         | 
| 282 233 | 
             
              const { font, pdfFontObj, fallbackFontName } = fontSetting;
         | 
| 283 234 |  | 
| 284 235 | 
             
              const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName];
         | 
| 285 | 
            -
              const fontKitFont = await getFontKitFont(templateSchema, font)
         | 
| 236 | 
            +
              const fontKitFont = await getFontKitFont(templateSchema, font);
         | 
| 286 237 |  | 
| 238 | 
            +
              const pageHeight = page.getHeight();
         | 
| 287 239 | 
             
              drawBackgroundColor({ templateSchema, page, pageHeight });
         | 
| 288 240 |  | 
| 289 | 
            -
              const { width, height, rotate } =  | 
| 290 | 
            -
              const {  | 
| 291 | 
            -
                 | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 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 | 
            +
                });
         | 
| 295 248 |  | 
| 296 249 | 
             
              page.pushOperators(setCharacterSpacing(characterSpacing));
         | 
| 297 250 |  | 
| 298 | 
            -
               | 
| 251 | 
            +
              const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
         | 
| 252 | 
            +
              const descent = getFontDescentInPt(fontKitFont, fontSize);
         | 
| 253 | 
            +
              const halfLineHeightAdjustment = lineHeight === 0 ? 0 : ((lineHeight - 1) * fontSize) / 2;
         | 
| 299 254 |  | 
| 300 | 
            -
              const  | 
| 301 | 
            -
                 | 
| 302 | 
            -
             | 
| 303 | 
            -
                 | 
| 255 | 
            +
              const fontWidthCalcValues: FontWidthCalcValues = {
         | 
| 256 | 
            +
                font: fontKitFont,
         | 
| 257 | 
            +
                fontSize,
         | 
| 258 | 
            +
                characterSpacing,
         | 
| 259 | 
            +
                boxWidthInPt: width,
         | 
| 304 260 | 
             
              };
         | 
| 305 | 
            -
              input.split(/\r|\n|\r\n/g).forEach((inputLine, inputLineIndex) => {
         | 
| 306 | 
            -
                const splitLines = getSplittedLines(inputLine, isOverEval);
         | 
| 307 | 
            -
             | 
| 308 | 
            -
                const drawLine = (line: string, lineIndex: number) => {
         | 
| 309 | 
            -
                  const textWidth = pdfFontValue.widthOfTextAtSize(line, size) + (line.length - 1) * characterSpacing;
         | 
| 310 | 
            -
                  const textHeight = heightOfFontAtSize(fontKitFont, size);
         | 
| 311 | 
            -
             | 
| 312 | 
            -
                  page.drawText(line, {
         | 
| 313 | 
            -
                    x: calcX(templateSchema.position.x, alignment, width, textWidth),
         | 
| 314 | 
            -
                    y:
         | 
| 315 | 
            -
                      calcY(templateSchema.position.y, pageHeight, height) +
         | 
| 316 | 
            -
                      height -
         | 
| 317 | 
            -
                      textHeight -
         | 
| 318 | 
            -
                      lineHeight * size * (inputLineIndex + lineIndex + beforeLineOver) -
         | 
| 319 | 
            -
                      (lineHeight === 0 ? 0 : ((lineHeight - 1) * size) / 2),
         | 
| 320 | 
            -
                    rotate,
         | 
| 321 | 
            -
                    size,
         | 
| 322 | 
            -
                    color,
         | 
| 323 | 
            -
                    lineHeight: lineHeight * size,
         | 
| 324 | 
            -
                    maxWidth: width,
         | 
| 325 | 
            -
                    font: pdfFontValue,
         | 
| 326 | 
            -
                    wordBreaks: [''],
         | 
| 327 | 
            -
                  });
         | 
| 328 | 
            -
                  if (splitLines.length === lineIndex + 1) beforeLineOver += lineIndex;
         | 
| 329 | 
            -
                };
         | 
| 330 261 |  | 
| 331 | 
            -
             | 
| 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 | 
            +
                });
         | 
| 332 296 | 
             
              });
         | 
| 333 297 | 
             
            };
         | 
| 334 298 |  | 
| @@ -337,17 +301,16 @@ const getCacheKey = (templateSchema: Schema, input: string) => `${templateSchema | |
| 337 301 | 
             
            const drawInputByImageSchema = async (arg: {
         | 
| 338 302 | 
             
              input: string;
         | 
| 339 303 | 
             
              templateSchema: ImageSchema;
         | 
| 340 | 
            -
              pageHeight: number;
         | 
| 341 304 | 
             
              pdfDoc: PDFDocument;
         | 
| 342 305 | 
             
              page: PDFPage;
         | 
| 343 306 | 
             
              inputImageCache: InputImageCache;
         | 
| 344 307 | 
             
            }) => {
         | 
| 345 | 
            -
              const { input, templateSchema,  | 
| 308 | 
            +
              const { input, templateSchema, pdfDoc, page, inputImageCache } = arg;
         | 
| 346 309 |  | 
| 347 | 
            -
              const { width, height, rotate } =  | 
| 310 | 
            +
              const { width, height, rotate } = convertSchemaDimensionsToPt(templateSchema);
         | 
| 348 311 | 
             
              const opt = {
         | 
| 349 312 | 
             
                x: calcX(templateSchema.position.x, 'left', width, width),
         | 
| 350 | 
            -
                y: calcY(templateSchema.position.y,  | 
| 313 | 
            +
                y: calcY(templateSchema.position.y, page.getHeight(), height),
         | 
| 351 314 | 
             
                rotate,
         | 
| 352 315 | 
             
                width,
         | 
| 353 316 | 
             
                height,
         | 
| @@ -365,18 +328,17 @@ const drawInputByImageSchema = async (arg: { | |
| 365 328 | 
             
            const drawInputByBarcodeSchema = async (arg: {
         | 
| 366 329 | 
             
              input: string;
         | 
| 367 330 | 
             
              templateSchema: BarcodeSchema;
         | 
| 368 | 
            -
              pageHeight: number;
         | 
| 369 331 | 
             
              pdfDoc: PDFDocument;
         | 
| 370 332 | 
             
              page: PDFPage;
         | 
| 371 333 | 
             
              inputImageCache: InputImageCache;
         | 
| 372 334 | 
             
            }) => {
         | 
| 373 | 
            -
              const { input, templateSchema,  | 
| 335 | 
            +
              const { input, templateSchema, pdfDoc, page, inputImageCache } = arg;
         | 
| 374 336 | 
             
              if (!validateBarcodeInput(templateSchema.type as BarCodeType, input)) return;
         | 
| 375 337 |  | 
| 376 | 
            -
              const { width, height, rotate } =  | 
| 338 | 
            +
              const { width, height, rotate } = convertSchemaDimensionsToPt(templateSchema);
         | 
| 377 339 | 
             
              const opt = {
         | 
| 378 340 | 
             
                x: calcX(templateSchema.position.x, 'left', width, width),
         | 
| 379 | 
            -
                y: calcY(templateSchema.position.y,  | 
| 341 | 
            +
                y: calcY(templateSchema.position.y, page.getHeight(), height),
         | 
| 380 342 | 
             
                rotate,
         | 
| 381 343 | 
             
                width,
         | 
| 382 344 | 
             
                height,
         | 
| @@ -398,7 +360,6 @@ export const drawInputByTemplateSchema = async (arg: { | |
| 398 360 | 
             
              templateSchema: Schema;
         | 
| 399 361 | 
             
              pdfDoc: PDFDocument;
         | 
| 400 362 | 
             
              page: PDFPage;
         | 
| 401 | 
            -
              pageHeight: number;
         | 
| 402 363 | 
             
              fontSetting: FontSetting;
         | 
| 403 364 | 
             
              inputImageCache: InputImageCache;
         | 
| 404 365 | 
             
            }) => {
         |