@pdfme/common 4.5.2-dev.2 → 4.5.2-dev.5

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.
@@ -4,7 +4,7 @@ import type { PDFPage, PDFDocument } from '@pdfme/pdf-lib';
4
4
  import type { ThemeConfig, GlobalToken } from 'antd';
5
5
  /** @ts-ignore -- optional interface, will gracefully degrade to `any` if `form-render` isn't installed*/
6
6
  import type { WidgetProps as _PropPanelWidgetProps, Schema as _PropPanelSchema } from 'form-render';
7
- import { Lang, Dict, Mode, Size, Schema, Font, SchemaForUI, BasePdf, BlankPdf, CommonOptions, Template, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, ColorType } from './schema.js';
7
+ import { Lang, Dict, Mode, Size, Schema, Font, SchemaForUI, BasePdf, BlankPdf, CommonOptions, Template, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, ColorType, LegacySchemaPageArray, SchemaPageArray } from './schema.js';
8
8
  export type PropPanelSchema = _PropPanelSchema;
9
9
  export type ChangeSchemaItem = {
10
10
  key: string;
@@ -15,7 +15,6 @@ export type ChangeSchemas = (objs: ChangeSchemaItem[]) => void;
15
15
  /**
16
16
  * Properties used for PDF rendering.
17
17
  * @template T Type of the extended Schema object.
18
- * @property {string} key The key of the schema object.
19
18
  * @property {string} value The string used for PDF rendering.
20
19
  * @property {T} schema Extended Schema object for rendering.
21
20
  * @property {BasePdf} basePdf Base PDF object for rendering.
@@ -26,7 +25,6 @@ export type ChangeSchemas = (objs: ChangeSchemaItem[]) => void;
26
25
  * @property {Map<any, any>} _cache Cache shared only during the execution of the generate function (useful for caching images, etc. if needed).
27
26
  */
28
27
  export interface PDFRenderProps<T extends Schema> {
29
- key: string;
30
28
  value: string;
31
29
  schema: T;
32
30
  basePdf: BasePdf;
@@ -63,7 +61,6 @@ export type UIRenderProps<T extends Schema> = {
63
61
  tabIndex?: number;
64
62
  placeholder?: string;
65
63
  stopEditing?: () => void;
66
- key: string;
67
64
  value: string;
68
65
  onChange?: (arg: {
69
66
  key: string;
@@ -173,4 +170,6 @@ export type PreviewProps = z.infer<typeof PreviewProps> & {
173
170
  export type DesignerProps = z.infer<typeof DesignerProps> & {
174
171
  plugins?: Plugins;
175
172
  };
173
+ export type SchemaPageArray = z.infer<typeof SchemaPageArray>;
174
+ export type LegacySchemaPageArray = z.infer<typeof LegacySchemaPageArray>;
176
175
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/common",
3
- "version": "4.5.2-dev.2",
3
+ "version": "4.5.2-dev.5",
4
4
  "sideEffects": false,
5
5
  "author": "hand-dot",
6
6
  "license": "MIT",
package/src/constants.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // TODO: Automatically retrieve and apply the current git tag during the build process.
2
- export const PDFME_VERSION = '4.0.0';
2
+ export const PDFME_VERSION = '5.0.0';
3
3
  export const PT_TO_PX_RATIO = 1.333;
4
4
  export const PT_TO_MM_RATIO = 0.3528;
5
5
  export const MM_TO_PT_RATIO = 2.8346; // https://www.ddc.co.jp/words/archives/20090701114500.html
package/src/helper.ts CHANGED
@@ -1,6 +1,16 @@
1
1
  import { z } from 'zod';
2
2
  import { Buffer } from 'buffer';
3
- import { Schema, Template, Font, BasePdf, Plugins, BlankPdf, CommonOptions } from './types';
3
+ import {
4
+ Schema,
5
+ Template,
6
+ Font,
7
+ BasePdf,
8
+ Plugins,
9
+ BlankPdf,
10
+ CommonOptions,
11
+ LegacySchemaPageArray,
12
+ SchemaPageArray
13
+ } from './types';
4
14
  import {
5
15
  Inputs as InputsSchema,
6
16
  UIOptions as UIOptionsSchema,
@@ -79,12 +89,34 @@ export const isHexValid = (hex: string): boolean => {
79
89
  return /^#(?:[A-Fa-f0-9]{3,4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/i.test(hex);
80
90
  };
81
91
 
92
+ /**
93
+ * Migrate from legacy keyed object format to array format
94
+ * @param template Template
95
+ */
96
+ export const migrateTemplate = (template: Template) => {
97
+ if (!template.schemas) {
98
+ return;
99
+ }
100
+
101
+ if (Array.isArray(template.schemas) && template.schemas.length > 0 && !Array.isArray(template.schemas[0])) {
102
+ template.schemas = (template.schemas as unknown as LegacySchemaPageArray).map(
103
+ (page: Record<string, Schema>) =>
104
+ Object.entries(page).map(([key, value]) => ({
105
+ ...value,
106
+ name: key,
107
+ }))
108
+ );
109
+ }
110
+ };
111
+
82
112
  export const getInputFromTemplate = (template: Template): { [key: string]: string }[] => {
113
+ migrateTemplate(template);
114
+
83
115
  const input: { [key: string]: string } = {};
84
- template.schemas.forEach((schema) => {
85
- Object.entries(schema).forEach(([key, value]) => {
86
- if (!value.readOnly) {
87
- input[key] = value.content || '';
116
+ template.schemas.forEach(page => {
117
+ page.forEach(schema => {
118
+ if (!schema.readOnly) {
119
+ input[schema.name] = schema.content || '';
88
120
  }
89
121
  });
90
122
  });
@@ -124,10 +156,10 @@ export const b64toUint8Array = (base64: string) => {
124
156
  return unit8arr;
125
157
  };
126
158
 
127
- const getFontNamesInSchemas = (schemas: { [key: string]: Schema }[]) =>
159
+ const getFontNamesInSchemas = (schemas: SchemaPageArray) =>
128
160
  uniq(
129
161
  schemas
130
- .map((s) => Object.values(s).map((v) => (v as any).fontName ?? ''))
162
+ .map((p) => p.map((v) => (v as any).fontName ?? ''))
131
163
  .reduce((acc, cur) => acc.concat(cur), [] as (string | undefined)[])
132
164
  .filter(Boolean) as string[]
133
165
  );
@@ -169,7 +201,7 @@ export const checkPlugins = (arg: { plugins: Plugins; template: Template }) => {
169
201
  plugins,
170
202
  template: { schemas },
171
203
  } = arg;
172
- const allSchemaTypes = uniq(schemas.map((s) => Object.values(s).map((v) => v.type)).flat());
204
+ const allSchemaTypes = uniq(schemas.map((p) => p.map((v) => v.type)).flat());
173
205
 
174
206
  const pluginsSchemaTypes = Object.values(plugins).map((p) => p?.propPanel.defaultSchema.type);
175
207
 
@@ -219,11 +251,24 @@ ${message}`);
219
251
 
220
252
  export const checkInputs = (data: unknown) => checkProps(data, InputsSchema);
221
253
  export const checkUIOptions = (data: unknown) => checkProps(data, UIOptionsSchema);
222
- export const checkTemplate = (data: unknown) => checkProps(data, TemplateSchema);
223
- export const checkUIProps = (data: unknown) => checkProps(data, UIPropsSchema);
224
254
  export const checkPreviewProps = (data: unknown) => checkProps(data, PreviewPropsSchema);
225
255
  export const checkDesignerProps = (data: unknown) => checkProps(data, DesignerPropsSchema);
226
- export const checkGenerateProps = (data: unknown) => checkProps(data, GeneratePropsSchema);
256
+ export const checkUIProps = (data: unknown) => {
257
+ if (typeof data === 'object' && data !== null && 'template' in data) {
258
+ migrateTemplate(data.template as Template);
259
+ }
260
+ checkProps(data, UIPropsSchema);
261
+ }
262
+ export const checkTemplate = (template: unknown) => {
263
+ migrateTemplate(template as Template);
264
+ checkProps(template, TemplateSchema);
265
+ }
266
+ export const checkGenerateProps = (data: unknown) => {
267
+ if (typeof data === 'object' && data !== null && 'template' in data) {
268
+ migrateTemplate(data.template as Template);
269
+ }
270
+ checkProps(data, GeneratePropsSchema);
271
+ }
227
272
 
228
273
  interface ModifyTemplateForDynamicTableArg {
229
274
  template: Template;
@@ -239,7 +284,6 @@ interface ModifyTemplateForDynamicTableArg {
239
284
  class Node {
240
285
  index = 0;
241
286
 
242
- key?: string;
243
287
  schema?: Schema;
244
288
 
245
289
  children: Node[] = [];
@@ -258,8 +302,7 @@ class Node {
258
302
  this.index = index;
259
303
  }
260
304
 
261
- setKeyAndSchema(key: string, schema: Schema): void {
262
- this.key = key;
305
+ setSchema(schema: Schema): void {
263
306
  this.schema = schema;
264
307
  }
265
308
 
@@ -301,24 +344,23 @@ function createPage(basePdf: BlankPdf) {
301
344
  }
302
345
 
303
346
  function createNode(arg: {
304
- key: string;
305
347
  schema: Schema;
306
348
  position: { x: number; y: number };
307
349
  width: number;
308
350
  height: number;
309
351
  }) {
310
- const { position, width, height, key, schema } = arg;
352
+ const { position, width, height, schema } = arg;
311
353
  const node = new Node({ width, height });
312
354
  node.setPosition(position);
313
- node.setKeyAndSchema(key, schema);
355
+ node.setSchema(schema);
314
356
  return node;
315
357
  }
316
358
 
317
359
  function resortChildren(page: Node, orderMap: Map<string, number>): void {
318
360
  page.children = page.children
319
361
  .sort((a, b) => {
320
- const orderA = orderMap.get(a.key!);
321
- const orderB = orderMap.get(b.key!);
362
+ const orderA = orderMap.get(a.schema?.name!);
363
+ const orderB = orderMap.get(b.schema?.name!);
322
364
  if (orderA === undefined || orderB === undefined) {
323
365
  throw new Error('[@pdfme/common] order is not defined');
324
366
  }
@@ -333,23 +375,21 @@ function resortChildren(page: Node, orderMap: Map<string, number>): void {
333
375
  async function createOnePage(
334
376
  arg: {
335
377
  basePdf: BlankPdf;
336
- schemaObj: Record<string, Schema>;
378
+ schemaPage: Schema[];
337
379
  orderMap: Map<string, number>;
338
380
  } & Omit<ModifyTemplateForDynamicTableArg, 'template'>
339
381
  ): Promise<Node> {
340
- const { basePdf, schemaObj, orderMap, input, options, _cache, getDynamicHeights } = arg;
382
+ const { basePdf, schemaPage, orderMap, input, options, _cache, getDynamicHeights } = arg;
341
383
  const page = createPage(basePdf);
342
384
 
343
385
  const schemaPositions: number[] = [];
344
- const sortedSchemaEntries = Object.entries(schemaObj).sort(
345
- (a, b) => a[1].position.y - b[1].position.y
346
- );
386
+ const sortedSchemaEntries = cloneDeep(schemaPage).sort((a, b) => a.position.y - b.position.y);
347
387
  const diffMap = new Map();
348
- for (const [key, schema] of sortedSchemaEntries) {
388
+ for (const schema of sortedSchemaEntries) {
349
389
  const { position, width } = schema;
350
390
 
351
391
  const opt = { schema, basePdf, options, _cache };
352
- const value = (schema.readOnly ? schema.content : input?.[key]) || '';
392
+ const value = (schema.readOnly ? schema.content : input?.[schema.name]) || '';
353
393
  const heights = await getDynamicHeights(value, opt);
354
394
 
355
395
  const heightsSum = heights.reduce((acc, cur) => acc + cur, 0);
@@ -364,7 +404,7 @@ async function createOnePage(
364
404
  y += diff;
365
405
  }
366
406
  }
367
- const node = createNode({ key, schema, position: { ...position, y }, width, height });
407
+ const node = createNode({ schema, position: { ...position, y }, width, height });
368
408
 
369
409
  schemaPositions.push(y + height + basePdf.padding[2]);
370
410
  page.insertChild(node);
@@ -406,7 +446,7 @@ function breakIntoPages(arg: {
406
446
 
407
447
  const children = longPage.children.sort((a, b) => a.position.y - b.position.y);
408
448
  for (let i = 0; i < children.length; i++) {
409
- const { key, schema, position, height, width } = children[i];
449
+ const { schema, position, height, width } = children[i];
410
450
  const { y, x } = position;
411
451
 
412
452
  let targetPageIndex = Math.floor(y / getPageHeight(pages.length - 1));
@@ -417,9 +457,9 @@ function breakIntoPages(arg: {
417
457
  newY = calculateNewY(y, targetPageIndex);
418
458
  }
419
459
 
420
- if (!key || !schema) throw new Error('[@pdfme/common] key or schema is undefined');
460
+ if (!schema) throw new Error('[@pdfme/common] schema is undefined');
421
461
 
422
- const clonedElement = createNode({ key, schema, position: { x, y: newY }, width, height });
462
+ const clonedElement = createNode({ schema, position: { x, y: newY }, width, height });
423
463
  pages[targetPageIndex].insertChild(clonedElement);
424
464
  }
425
465
 
@@ -430,46 +470,53 @@ function breakIntoPages(arg: {
430
470
 
431
471
  function createNewTemplate(pages: Node[], basePdf: BlankPdf): Template {
432
472
  const newTemplate: Template = {
433
- schemas: Array.from({ length: pages.length }, () => ({} as Record<string, Schema>)),
473
+ schemas: Array.from({ length: pages.length }, () => ([] as Schema[])),
434
474
  basePdf: basePdf,
435
475
  };
436
476
 
437
- const keyToSchemas = new Map<string, Node[]>();
477
+ const nameToSchemas = new Map<string, Node[]>();
438
478
 
439
479
  cloneDeep(pages).forEach((page, pageIndex) => {
440
480
  page.children.forEach((child) => {
441
- const { key, schema } = child;
442
- if (!key || !schema) throw new Error('[@pdfme/common] key or schema is undefined');
481
+ const { schema } = child;
482
+ if (!schema) throw new Error('[@pdfme/common] schema is undefined');
443
483
 
444
- if (!keyToSchemas.has(key)) {
445
- keyToSchemas.set(key, []);
484
+ const name = schema.name
485
+ if (!nameToSchemas.has(name)) {
486
+ nameToSchemas.set(name, []);
446
487
  }
447
- keyToSchemas.get(key)!.push(child);
488
+ nameToSchemas.get(name)!.push(child);
448
489
 
449
- const sameKeySchemas = page.children.filter((c) => c.key === key);
450
- const start = keyToSchemas.get(key)!.length - sameKeySchemas.length;
490
+ const sameNameSchemas = page.children.filter((c) => c.schema?.name === name);
491
+ const start = nameToSchemas.get(name)!.length - sameNameSchemas.length;
451
492
 
452
- if (sameKeySchemas.length > 0) {
453
- if (!sameKeySchemas[0].schema) {
493
+ if (sameNameSchemas.length > 0) {
494
+ if (!sameNameSchemas[0].schema) {
454
495
  throw new Error('[@pdfme/common] schema is undefined');
455
496
  }
456
497
 
457
498
  // Use the first schema to get the schema and position
458
- const schema = sameKeySchemas[0].schema;
459
- const height = sameKeySchemas.reduce((acc, cur) => acc + cur.height, 0);
460
- const position = sameKeySchemas[0].position;
499
+ const schema = sameNameSchemas[0].schema;
500
+ const height = sameNameSchemas.reduce((acc, cur) => acc + cur.height, 0);
501
+ const position = sameNameSchemas[0].position;
461
502
 
462
503
  // Currently, __bodyRange exists for table schemas, but if we make it more abstract,
463
504
  // it could be used for other schemas as well to render schemas that have been split by page breaks, starting from the middle.
464
505
  schema.__bodyRange = {
465
506
  start: Math.max(start - 1, 0),
466
- end: start + sameKeySchemas.length - 1,
507
+ end: start + sameNameSchemas.length - 1,
467
508
  };
468
509
 
469
510
  // Currently, this is used to determine whether to display the header when a table is split.
470
511
  schema.__isSplit = start > 0;
471
512
 
472
- newTemplate.schemas[pageIndex][key] = Object.assign({}, schema, { position, height });
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
+ }
473
520
  }
474
521
  });
475
522
  });
@@ -488,10 +535,9 @@ export const getDynamicTemplate = async (
488
535
  const basePdf = template.basePdf as BlankPdf;
489
536
  const pages: Node[] = [];
490
537
 
491
- for (const schemaObj of template.schemas) {
492
- const orderMap = new Map(Object.keys(schemaObj).map((key, index) => [key, index]));
493
-
494
- const longPage = await createOnePage({ basePdf, schemaObj, orderMap, ...arg });
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 });
495
541
  const brokenPages = breakIntoPages({ longPage, basePdf, orderMap });
496
542
  pages.push(...brokenPages);
497
543
  }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  import type {
11
11
  ChangeSchemaItem,
12
12
  ChangeSchemas,
13
+ SchemaPageArray,
13
14
  PropPanel,
14
15
  PropPanelSchema,
15
16
  PropPanelWidgetProps,
@@ -112,6 +113,7 @@ export type {
112
113
  DesignerProps,
113
114
  ChangeSchemaItem,
114
115
  ChangeSchemas,
116
+ SchemaPageArray,
115
117
  PropPanel,
116
118
  PropPanelSchema,
117
119
  PropPanelWidgetProps,
package/src/schema.ts CHANGED
@@ -84,6 +84,7 @@ export const Size = z.object({ height: z.number(), width: z.number() });
84
84
 
85
85
  export const Schema = z
86
86
  .object({
87
+ name: z.string(),
87
88
  type: z.string(),
88
89
  content: z.string().optional(),
89
90
  position: z.object({ x: z.number(), y: z.number() }),
@@ -98,10 +99,7 @@ export const Schema = z
98
99
  })
99
100
  .passthrough();
100
101
 
101
- const SchemaForUIAdditionalInfo = z.object({
102
- id: z.string(),
103
- key: z.string(),
104
- });
102
+ const SchemaForUIAdditionalInfo = z.object({ id: z.string() });
105
103
  export const SchemaForUI = Schema.merge(SchemaForUIAdditionalInfo);
106
104
 
107
105
  const ArrayBufferSchema: z.ZodSchema<ArrayBuffer> = z.any().refine((v) => v instanceof ArrayBuffer);
@@ -117,9 +115,13 @@ const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]);
117
115
 
118
116
  export const BasePdf = z.union([CustomPdf, BlankPdf]);
119
117
 
118
+ // Legacy keyed structure for BC - we convert to SchemaPageArray on import
119
+ export const LegacySchemaPageArray = z.array(z.record(Schema));
120
+ export const SchemaPageArray = z.array(z.array(Schema));
121
+
120
122
  export const Template = z
121
123
  .object({
122
- schemas: z.array(z.record(Schema)),
124
+ schemas: SchemaPageArray,
123
125
  basePdf: BasePdf,
124
126
  pdfmeVersion: z.string().optional(),
125
127
  })
package/src/types.ts CHANGED
@@ -23,6 +23,8 @@ import {
23
23
  PreviewProps,
24
24
  DesignerProps,
25
25
  ColorType,
26
+ LegacySchemaPageArray,
27
+ SchemaPageArray,
26
28
  } from './schema.js';
27
29
 
28
30
  export type PropPanelSchema = _PropPanelSchema;
@@ -36,7 +38,6 @@ export type ChangeSchemas = (objs: ChangeSchemaItem[]) => void;
36
38
  /**
37
39
  * Properties used for PDF rendering.
38
40
  * @template T Type of the extended Schema object.
39
- * @property {string} key The key of the schema object.
40
41
  * @property {string} value The string used for PDF rendering.
41
42
  * @property {T} schema Extended Schema object for rendering.
42
43
  * @property {BasePdf} basePdf Base PDF object for rendering.
@@ -47,7 +48,6 @@ export type ChangeSchemas = (objs: ChangeSchemaItem[]) => void;
47
48
  * @property {Map<any, any>} _cache Cache shared only during the execution of the generate function (useful for caching images, etc. if needed).
48
49
  */
49
50
  export interface PDFRenderProps<T extends Schema> {
50
- key: string;
51
51
  value: string;
52
52
  schema: T;
53
53
  basePdf: BasePdf;
@@ -86,7 +86,6 @@ export type UIRenderProps<T extends Schema> = {
86
86
  tabIndex?: number;
87
87
  placeholder?: string;
88
88
  stopEditing?: () => void;
89
- key: string;
90
89
  value: string;
91
90
  onChange?: (arg: { key: string; value: any } | { key: string; value: any }[]) => void;
92
91
  rootElement: HTMLDivElement;
@@ -186,3 +185,5 @@ export type UIOptions = z.infer<typeof UIOptions> & { theme?: ThemeConfig };
186
185
  export type UIProps = z.infer<typeof UIProps> & { plugins?: Plugins };
187
186
  export type PreviewProps = z.infer<typeof PreviewProps> & { plugins?: Plugins };
188
187
  export type DesignerProps = z.infer<typeof DesignerProps> & { plugins?: Plugins };
188
+ export type SchemaPageArray = z.infer<typeof SchemaPageArray>;
189
+ export type LegacySchemaPageArray = z.infer<typeof LegacySchemaPageArray>;