@pdfme/common 5.1.6-dev.2 → 5.1.7-dev.2

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 (50) hide show
  1. package/dist/cjs/__tests__/dynamicTemplate.test.js +197 -0
  2. package/dist/cjs/__tests__/dynamicTemplate.test.js.map +1 -0
  3. package/dist/cjs/__tests__/expression.test.js +271 -0
  4. package/dist/cjs/__tests__/expression.test.js.map +1 -0
  5. package/dist/cjs/__tests__/helper.test.js +92 -254
  6. package/dist/cjs/__tests__/helper.test.js.map +1 -1
  7. package/dist/cjs/src/constants.js +6 -0
  8. package/dist/cjs/src/constants.js.map +1 -1
  9. package/dist/cjs/src/dynamicTemplate.js +239 -0
  10. package/dist/cjs/src/dynamicTemplate.js.map +1 -0
  11. package/dist/cjs/src/expression.js +392 -0
  12. package/dist/cjs/src/expression.js.map +1 -0
  13. package/dist/cjs/src/helper.js +6 -238
  14. package/dist/cjs/src/helper.js.map +1 -1
  15. package/dist/cjs/src/index.js +5 -2
  16. package/dist/cjs/src/index.js.map +1 -1
  17. package/dist/cjs/src/schema.js +1 -0
  18. package/dist/cjs/src/schema.js.map +1 -1
  19. package/dist/esm/__tests__/dynamicTemplate.test.js +172 -0
  20. package/dist/esm/__tests__/dynamicTemplate.test.js.map +1 -0
  21. package/dist/esm/__tests__/expression.test.js +269 -0
  22. package/dist/esm/__tests__/expression.test.js.map +1 -0
  23. package/dist/esm/__tests__/helper.test.js +94 -256
  24. package/dist/esm/__tests__/helper.test.js.map +1 -1
  25. package/dist/esm/src/constants.js +6 -0
  26. package/dist/esm/src/constants.js.map +1 -1
  27. package/dist/esm/src/dynamicTemplate.js +235 -0
  28. package/dist/esm/src/dynamicTemplate.js.map +1 -0
  29. package/dist/esm/src/expression.js +365 -0
  30. package/dist/esm/src/expression.js.map +1 -0
  31. package/dist/esm/src/helper.js +5 -236
  32. package/dist/esm/src/helper.js.map +1 -1
  33. package/dist/esm/src/index.js +4 -2
  34. package/dist/esm/src/index.js.map +1 -1
  35. package/dist/esm/src/schema.js +1 -0
  36. package/dist/esm/src/schema.js.map +1 -1
  37. package/dist/types/__tests__/dynamicTemplate.test.d.ts +1 -0
  38. package/dist/types/__tests__/expression.test.d.ts +1 -0
  39. package/dist/types/src/dynamicTemplate.d.ts +15 -0
  40. package/dist/types/src/expression.d.ts +6 -0
  41. package/dist/types/src/helper.d.ts +34 -15
  42. package/dist/types/src/index.d.ts +4 -2
  43. package/dist/types/src/schema.d.ts +3631 -517
  44. package/package.json +5 -1
  45. package/src/constants.ts +8 -0
  46. package/src/dynamicTemplate.ts +277 -0
  47. package/src/expression.ts +392 -0
  48. package/src/helper.ts +10 -282
  49. package/src/index.ts +3 -1
  50. package/src/schema.ts +1 -0
package/src/helper.ts CHANGED
@@ -7,9 +7,8 @@ import {
7
7
  BasePdf,
8
8
  Plugins,
9
9
  BlankPdf,
10
- CommonOptions,
11
10
  LegacySchemaPageArray,
12
- SchemaPageArray
11
+ SchemaPageArray,
13
12
  } from './types';
14
13
  import {
15
14
  Inputs as InputsSchema,
@@ -98,7 +97,11 @@ export const migrateTemplate = (template: Template) => {
98
97
  return;
99
98
  }
100
99
 
101
- if (Array.isArray(template.schemas) && template.schemas.length > 0 && !Array.isArray(template.schemas[0])) {
100
+ if (
101
+ Array.isArray(template.schemas) &&
102
+ template.schemas.length > 0 &&
103
+ !Array.isArray(template.schemas[0])
104
+ ) {
102
105
  template.schemas = (template.schemas as unknown as LegacySchemaPageArray).map(
103
106
  (page: Record<string, Schema>) =>
104
107
  Object.entries(page).map(([key, value]) => ({
@@ -113,8 +116,8 @@ export const getInputFromTemplate = (template: Template): { [key: string]: strin
113
116
  migrateTemplate(template);
114
117
 
115
118
  const input: { [key: string]: string } = {};
116
- template.schemas.forEach(page => {
117
- page.forEach(schema => {
119
+ template.schemas.forEach((page) => {
120
+ page.forEach((schema) => {
118
121
  if (!schema.readOnly) {
119
122
  input[schema.name] = schema.content || '';
120
123
  }
@@ -258,289 +261,14 @@ export const checkUIProps = (data: unknown) => {
258
261
  migrateTemplate(data.template as Template);
259
262
  }
260
263
  checkProps(data, UIPropsSchema);
261
- }
264
+ };
262
265
  export const checkTemplate = (template: unknown) => {
263
266
  migrateTemplate(template as Template);
264
267
  checkProps(template, TemplateSchema);
265
- }
268
+ };
266
269
  export const checkGenerateProps = (data: unknown) => {
267
270
  if (typeof data === 'object' && data !== null && 'template' in data) {
268
271
  migrateTemplate(data.template as Template);
269
272
  }
270
273
  checkProps(data, GeneratePropsSchema);
271
- }
272
-
273
- interface ModifyTemplateForDynamicTableArg {
274
- template: Template;
275
- input: Record<string, string>;
276
- _cache: Map<any, any>;
277
- options: CommonOptions;
278
- getDynamicHeights: (
279
- value: string,
280
- args: { schema: Schema; basePdf: BasePdf; options: CommonOptions; _cache: Map<any, any> }
281
- ) => Promise<number[]>;
282
- }
283
-
284
- class Node {
285
- index = 0;
286
-
287
- schema?: Schema;
288
-
289
- children: Node[] = [];
290
-
291
- width = 0;
292
- height = 0;
293
- padding: [number, number, number, number] = [0, 0, 0, 0];
294
- position: { x: number; y: number } = { x: 0, y: 0 };
295
-
296
- constructor({ width = 0, height = 0 } = {}) {
297
- this.width = width;
298
- this.height = height;
299
- }
300
-
301
- setIndex(index: number): void {
302
- this.index = index;
303
- }
304
-
305
- setSchema(schema: Schema): void {
306
- this.schema = schema;
307
- }
308
-
309
- setWidth(width: number): void {
310
- this.width = width;
311
- }
312
-
313
- setHeight(height: number): void {
314
- this.height = height;
315
- }
316
-
317
- setPadding(padding: [number, number, number, number]): void {
318
- this.padding = padding;
319
- }
320
-
321
- setPosition(position: { x: number; y: number }): void {
322
- this.position = position;
323
- }
324
-
325
- insertChild(child: Node): void {
326
- const index = this.getChildCount();
327
- child.setIndex(index);
328
- this.children.splice(index, 0, child);
329
- }
330
-
331
- getChildCount(): number {
332
- return this.children.length;
333
- }
334
-
335
- getChild(index: number): Node {
336
- return this.children[index];
337
- }
338
- }
339
-
340
- function createPage(basePdf: BlankPdf) {
341
- const page = new Node({ ...basePdf });
342
- page.setPadding(basePdf.padding);
343
- return page;
344
- }
345
-
346
- function createNode(arg: {
347
- schema: Schema;
348
- position: { x: number; y: number };
349
- width: number;
350
- height: number;
351
- }) {
352
- const { position, width, height, schema } = arg;
353
- const node = new Node({ width, height });
354
- node.setPosition(position);
355
- node.setSchema(schema);
356
- return node;
357
- }
358
-
359
- function resortChildren(page: Node, orderMap: Map<string, number>): void {
360
- page.children = page.children
361
- .sort((a, b) => {
362
- const orderA = orderMap.get(a.schema?.name!);
363
- const orderB = orderMap.get(b.schema?.name!);
364
- if (orderA === undefined || orderB === undefined) {
365
- throw new Error('[@pdfme/common] order is not defined');
366
- }
367
- return orderA - orderB;
368
- })
369
- .map((child, index) => {
370
- child.setIndex(index);
371
- return child;
372
- });
373
- }
374
-
375
- async function createOnePage(
376
- arg: {
377
- basePdf: BlankPdf;
378
- schemaPage: Schema[];
379
- orderMap: Map<string, number>;
380
- } & Omit<ModifyTemplateForDynamicTableArg, 'template'>
381
- ): Promise<Node> {
382
- const { basePdf, schemaPage, orderMap, input, options, _cache, getDynamicHeights } = arg;
383
- const page = createPage(basePdf);
384
-
385
- const schemaPositions: number[] = [];
386
- const sortedSchemaEntries = cloneDeep(schemaPage).sort((a, b) => a.position.y - b.position.y);
387
- const diffMap = new Map();
388
- for (const schema of sortedSchemaEntries) {
389
- const { position, width } = schema;
390
-
391
- const opt = { schema, basePdf, options, _cache };
392
- const value = (schema.readOnly ? schema.content : input?.[schema.name]) || '';
393
- const heights = await getDynamicHeights(value, opt);
394
-
395
- const heightsSum = heights.reduce((acc, cur) => acc + cur, 0);
396
- const originalHeight = schema.height;
397
- if (heightsSum !== originalHeight) {
398
- diffMap.set(position.y + originalHeight, heightsSum - originalHeight);
399
- }
400
- heights.forEach((height, index) => {
401
- let y = schema.position.y + heights.reduce((acc, cur, i) => (i < index ? acc + cur : acc), 0);
402
- for (const [diffY, diff] of diffMap.entries()) {
403
- if (diffY <= schema.position.y) {
404
- y += diff;
405
- }
406
- }
407
- const node = createNode({ schema, position: { ...position, y }, width, height });
408
-
409
- schemaPositions.push(y + height + basePdf.padding[2]);
410
- page.insertChild(node);
411
- });
412
- }
413
-
414
- const pageHeight = Math.max(...schemaPositions, basePdf.height - basePdf.padding[2]);
415
- page.setHeight(pageHeight);
416
-
417
- resortChildren(page, orderMap);
418
-
419
- return page;
420
- }
421
-
422
- function breakIntoPages(arg: {
423
- longPage: Node;
424
- orderMap: Map<string, number>;
425
- basePdf: BlankPdf;
426
- }): Node[] {
427
- const { longPage, orderMap, basePdf } = arg;
428
- const pages: Node[] = [createPage(basePdf)];
429
- const [paddingTop, , paddingBottom] = basePdf.padding;
430
- const yAdjustments: { page: number; value: number }[] = [];
431
-
432
- const getPageHeight = (pageIndex: number) =>
433
- basePdf.height - paddingBottom - (pageIndex > 0 ? paddingTop : 0);
434
-
435
- const calculateNewY = (y: number, pageIndex: number) => {
436
- const newY = y - pageIndex * (basePdf.height - paddingTop - paddingBottom);
437
-
438
- while (pages.length <= pageIndex) {
439
- if (!pages[pageIndex]) {
440
- pages.push(createPage(basePdf));
441
- yAdjustments.push({ page: pageIndex, value: (newY - paddingTop) * -1 });
442
- }
443
- }
444
- return newY + (yAdjustments.find((adj) => adj.page === pageIndex)?.value || 0);
445
- };
446
-
447
- const children = longPage.children.sort((a, b) => a.position.y - b.position.y);
448
- for (let i = 0; i < children.length; i++) {
449
- const { schema, position, height, width } = children[i];
450
- const { y, x } = position;
451
-
452
- let targetPageIndex = Math.floor(y / getPageHeight(pages.length - 1));
453
- let newY = calculateNewY(y, targetPageIndex);
454
-
455
- if (newY + height > basePdf.height - paddingBottom) {
456
- targetPageIndex++;
457
- newY = calculateNewY(y, targetPageIndex);
458
- }
459
-
460
- if (!schema) throw new Error('[@pdfme/common] schema is undefined');
461
-
462
- const clonedElement = createNode({ schema, position: { x, y: newY }, width, height });
463
- pages[targetPageIndex].insertChild(clonedElement);
464
- }
465
-
466
- pages.forEach((page) => resortChildren(page, orderMap));
467
-
468
- return pages;
469
- }
470
-
471
- function createNewTemplate(pages: Node[], basePdf: BlankPdf): Template {
472
- const newTemplate: Template = {
473
- schemas: Array.from({ length: pages.length }, () => ([] as Schema[])),
474
- basePdf: basePdf,
475
- };
476
-
477
- const nameToSchemas = new Map<string, Node[]>();
478
-
479
- cloneDeep(pages).forEach((page, pageIndex) => {
480
- page.children.forEach((child) => {
481
- const { schema } = child;
482
- if (!schema) throw new Error('[@pdfme/common] schema is undefined');
483
-
484
- const name = schema.name
485
- if (!nameToSchemas.has(name)) {
486
- nameToSchemas.set(name, []);
487
- }
488
- nameToSchemas.get(name)!.push(child);
489
-
490
- const sameNameSchemas = page.children.filter((c) => c.schema?.name === name);
491
- const start = nameToSchemas.get(name)!.length - sameNameSchemas.length;
492
-
493
- if (sameNameSchemas.length > 0) {
494
- if (!sameNameSchemas[0].schema) {
495
- throw new Error('[@pdfme/common] schema is undefined');
496
- }
497
-
498
- // Use the first schema to get the schema and position
499
- const schema = sameNameSchemas[0].schema;
500
- const height = sameNameSchemas.reduce((acc, cur) => acc + cur.height, 0);
501
- const position = sameNameSchemas[0].position;
502
-
503
- // Currently, __bodyRange exists for table schemas, but if we make it more abstract,
504
- // it could be used for other schemas as well to render schemas that have been split by page breaks, starting from the middle.
505
- schema.__bodyRange = {
506
- start: Math.max(start - 1, 0),
507
- end: start + sameNameSchemas.length - 1,
508
- };
509
-
510
- // Currently, this is used to determine whether to display the header when a table is split.
511
- schema.__isSplit = start > 0;
512
-
513
- const newSchema = Object.assign({}, schema, { position, height });
514
- const index = newTemplate.schemas[pageIndex].findIndex((s) => s.name === name);
515
- if (index !== -1) {
516
- newTemplate.schemas[pageIndex][index] = newSchema;
517
- } else {
518
- newTemplate.schemas[pageIndex].push(newSchema);
519
- }
520
- }
521
- });
522
- });
523
-
524
- return newTemplate;
525
- }
526
-
527
- export const getDynamicTemplate = async (
528
- arg: ModifyTemplateForDynamicTableArg
529
- ): Promise<Template> => {
530
- const { template } = arg;
531
- if (!isBlankPdf(template.basePdf)) {
532
- return template;
533
- }
534
-
535
- const basePdf = template.basePdf as BlankPdf;
536
- const pages: Node[] = [];
537
-
538
- for (const schemaPage of template.schemas) {
539
- const orderMap = new Map(schemaPage.map((schema, index) => [schema.name, index]));
540
- const longPage = await createOnePage({ basePdf, schemaPage, orderMap, ...arg });
541
- const brokenPages = breakIntoPages({ longPage, basePdf, orderMap });
542
- pages.push(...brokenPages);
543
- }
544
-
545
- return createNewTemplate(pages, template.basePdf);
546
274
  };
package/src/index.ts CHANGED
@@ -58,8 +58,9 @@ import {
58
58
  isHexValid,
59
59
  getInputFromTemplate,
60
60
  isBlankPdf,
61
- getDynamicTemplate,
62
61
  } from './helper';
62
+ import { getDynamicTemplate } from './dynamicTemplate';
63
+ import { replacePlaceholders } from './expression';
63
64
 
64
65
  export {
65
66
  PDFME_VERSION,
@@ -82,6 +83,7 @@ export {
82
83
  getInputFromTemplate,
83
84
  isBlankPdf,
84
85
  getDynamicTemplate,
86
+ replacePlaceholders,
85
87
  checkFont,
86
88
  checkInputs,
87
89
  checkUIOptions,
package/src/schema.ts CHANGED
@@ -115,6 +115,7 @@ export const BlankPdf = z.object({
115
115
  width: z.number(),
116
116
  height: z.number(),
117
117
  padding: z.tuple([z.number(), z.number(), z.number(), z.number()]),
118
+ staticSchema: z.array(Schema).optional(),
118
119
  });
119
120
 
120
121
  const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]);