@pdfme/generator 0.0.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/.vscode/settings.json +5 -0
- package/README.md +5 -0
- package/dist/cjs/__tests__/assets/templates/index.js +49 -0
- package/dist/cjs/__tests__/assets/templates/index.js.map +1 -0
- package/dist/cjs/__tests__/generate.test.js +277 -0
- package/dist/cjs/__tests__/generate.test.js.map +1 -0
- package/dist/cjs/__tests__/integration-other.test.js +70 -0
- package/dist/cjs/__tests__/integration-other.test.js.map +1 -0
- package/dist/cjs/__tests__/integration-playground.test.js +148 -0
- package/dist/cjs/__tests__/integration-playground.test.js.map +1 -0
- package/dist/cjs/__tests__/integration-segmenter.test.js +50 -0
- package/dist/cjs/__tests__/integration-segmenter.test.js.map +1 -0
- package/dist/cjs/__tests__/integration-textType.test.js +50 -0
- package/dist/cjs/__tests__/integration-textType.test.js.map +1 -0
- package/dist/cjs/__tests__/utils.js +70 -0
- package/dist/cjs/__tests__/utils.js.map +1 -0
- package/dist/cjs/src/constants.js +5 -0
- package/dist/cjs/src/constants.js.map +1 -0
- package/dist/cjs/src/generate.js +163 -0
- package/dist/cjs/src/generate.js.map +1 -0
- package/dist/cjs/src/helper.js +144 -0
- package/dist/cjs/src/helper.js.map +1 -0
- package/dist/cjs/src/index.js +9 -0
- package/dist/cjs/src/index.js.map +1 -0
- package/dist/cjs/src/types.js +3 -0
- package/dist/cjs/src/types.js.map +1 -0
- package/dist/esm/__tests__/assets/templates/index.js +46 -0
- package/dist/esm/__tests__/assets/templates/index.js.map +1 -0
- package/dist/esm/__tests__/generate.test.js +272 -0
- package/dist/esm/__tests__/generate.test.js.map +1 -0
- package/dist/esm/__tests__/integration-other.test.js +65 -0
- package/dist/esm/__tests__/integration-other.test.js.map +1 -0
- package/dist/esm/__tests__/integration-playground.test.js +110 -0
- package/dist/esm/__tests__/integration-playground.test.js.map +1 -0
- package/dist/esm/__tests__/integration-segmenter.test.js +45 -0
- package/dist/esm/__tests__/integration-segmenter.test.js.map +1 -0
- package/dist/esm/__tests__/integration-textType.test.js +45 -0
- package/dist/esm/__tests__/integration-textType.test.js.map +1 -0
- package/dist/esm/__tests__/utils.js +32 -0
- package/dist/esm/__tests__/utils.js.map +1 -0
- package/dist/esm/src/constants.js +2 -0
- package/dist/esm/src/constants.js.map +1 -0
- package/dist/esm/src/generate.js +128 -0
- package/dist/esm/src/generate.js.map +1 -0
- package/dist/esm/src/helper.js +103 -0
- package/dist/esm/src/helper.js.map +1 -0
- package/dist/esm/src/index.js +3 -0
- package/dist/esm/src/index.js.map +1 -0
- package/dist/esm/src/types.js +2 -0
- package/dist/esm/src/types.js.map +1 -0
- package/dist/node/__tests__/assets/templates/index.js +49 -0
- package/dist/node/__tests__/assets/templates/index.js.map +1 -0
- package/dist/node/__tests__/generate.test.js +277 -0
- package/dist/node/__tests__/generate.test.js.map +1 -0
- package/dist/node/__tests__/integration-other.test.js +70 -0
- package/dist/node/__tests__/integration-other.test.js.map +1 -0
- package/dist/node/__tests__/integration-playground.test.js +148 -0
- package/dist/node/__tests__/integration-playground.test.js.map +1 -0
- package/dist/node/__tests__/integration-segmenter.test.js +50 -0
- package/dist/node/__tests__/integration-segmenter.test.js.map +1 -0
- package/dist/node/__tests__/integration-textType.test.js +50 -0
- package/dist/node/__tests__/integration-textType.test.js.map +1 -0
- package/dist/node/__tests__/utils.js +70 -0
- package/dist/node/__tests__/utils.js.map +1 -0
- package/dist/node/src/constants.js +5 -0
- package/dist/node/src/constants.js.map +1 -0
- package/dist/node/src/generate.js +163 -0
- package/dist/node/src/generate.js.map +1 -0
- package/dist/node/src/helper.js +144 -0
- package/dist/node/src/helper.js.map +1 -0
- package/dist/node/src/index.js +9 -0
- package/dist/node/src/index.js.map +1 -0
- package/dist/node/src/types.js +3 -0
- package/dist/node/src/types.js.map +1 -0
- package/dist/types/__tests__/assets/templates/index.d.ts +975 -0
- package/dist/types/__tests__/generate.test.d.ts +1 -0
- package/dist/types/__tests__/integration-other.test.d.ts +1 -0
- package/dist/types/__tests__/integration-playground.test.d.ts +1 -0
- package/dist/types/__tests__/integration-segmenter.test.d.ts +1 -0
- package/dist/types/__tests__/integration-textType.test.d.ts +1 -0
- package/dist/types/__tests__/utils.d.ts +3 -0
- package/dist/types/src/constants.d.ts +1 -0
- package/dist/types/src/generate.d.ts +3 -0
- package/dist/types/src/helper.d.ts +29 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/types.d.ts +20 -0
- package/eslint.config.mjs +22 -0
- package/jest.setup.js +2 -0
- package/package.json +95 -0
- package/src/constants.ts +1 -0
- package/src/generate.ts +167 -0
- package/src/helper.ts +172 -0
- package/src/index.ts +3 -0
- package/src/types.ts +5 -0
- package/tsconfig.cjs.json +10 -0
- package/tsconfig.esm.json +11 -0
- package/tsconfig.json +18 -0
- package/tsconfig.node.json +11 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-image-snapshot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-image-snapshot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-image-snapshot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-image-snapshot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-image-snapshot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TOOL_NAME = "pdfme (https://pdfme.com/)";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Schema, Plugins, GeneratorOptions, Template, PDFRenderProps } from '@pdfme/common';
|
|
2
|
+
import { PDFPage, PDFDocument, PDFEmbeddedPage } from '@pdfme/pdf-lib';
|
|
3
|
+
import type { EmbedPdfBox } from './types.js';
|
|
4
|
+
export declare const getEmbedPdfPages: (arg: {
|
|
5
|
+
template: Template;
|
|
6
|
+
pdfDoc: PDFDocument;
|
|
7
|
+
}) => Promise<{
|
|
8
|
+
basePages: (PDFEmbeddedPage | PDFPage)[];
|
|
9
|
+
embedPdfBoxes: EmbedPdfBox[];
|
|
10
|
+
}>;
|
|
11
|
+
export declare const validateRequiredFields: (template: Template, inputs: Record<string, unknown>[]) => void;
|
|
12
|
+
export declare const preprocessing: (arg: {
|
|
13
|
+
template: Template;
|
|
14
|
+
userPlugins: Plugins;
|
|
15
|
+
}) => Promise<{
|
|
16
|
+
pdfDoc: PDFDocument;
|
|
17
|
+
renderObj: Record<string, (arg: PDFRenderProps<Schema & {
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}>) => Promise<void> | void>;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const postProcessing: (props: {
|
|
22
|
+
pdfDoc: PDFDocument;
|
|
23
|
+
options: GeneratorOptions;
|
|
24
|
+
}) => void;
|
|
25
|
+
export declare const insertPage: (arg: {
|
|
26
|
+
basePage: PDFEmbeddedPage | PDFPage;
|
|
27
|
+
embedPdfBox: EmbedPdfBox;
|
|
28
|
+
pdfDoc: PDFDocument;
|
|
29
|
+
}) => PDFPage;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type EmbedPdfBox = {
|
|
2
|
+
mediaBox: {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
};
|
|
8
|
+
bleedBox: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
14
|
+
trimBox: {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import { dirname, resolve } from 'path';
|
|
3
|
+
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
|
|
7
|
+
// Import the root config
|
|
8
|
+
const rootConfigPath = resolve(__dirname, '../../eslint.config.mjs');
|
|
9
|
+
const rootConfig = await import(rootConfigPath);
|
|
10
|
+
|
|
11
|
+
export default [
|
|
12
|
+
...rootConfig.default,
|
|
13
|
+
{
|
|
14
|
+
files: ['src/**/*.ts'],
|
|
15
|
+
languageOptions: {
|
|
16
|
+
parserOptions: {
|
|
17
|
+
project: ['./tsconfig.esm.json'],
|
|
18
|
+
tsconfigRootDir: __dirname,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
];
|
package/jest.setup.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pdfme/generator",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"author": "hand-dot",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pdf",
|
|
9
|
+
"pdf-generation",
|
|
10
|
+
"pdf-designer",
|
|
11
|
+
"pdf-viewer",
|
|
12
|
+
"typescript",
|
|
13
|
+
"react"
|
|
14
|
+
],
|
|
15
|
+
"description": "TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!",
|
|
16
|
+
"homepage": "https://pdfme.com",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git@github.com:pdfme/pdfme.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/pdfme/pdfme/issues"
|
|
23
|
+
},
|
|
24
|
+
"main": "dist/cjs/src/index.js",
|
|
25
|
+
"module": "dist/esm/src/index.js",
|
|
26
|
+
"types": "dist/types/src/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"import": {
|
|
30
|
+
"node": "./dist/node/src/index.js",
|
|
31
|
+
"default": "./dist/esm/src/index.js"
|
|
32
|
+
},
|
|
33
|
+
"require": "./dist/cjs/src/index.js",
|
|
34
|
+
"types": "./dist/types/src/index.d.ts"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "tsc -p tsconfig.esm.json -w",
|
|
39
|
+
"build": "run-p build:cjs build:esm build:node",
|
|
40
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
41
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
42
|
+
"build:node": "tsc -p tsconfig.node.json",
|
|
43
|
+
"clean": "rimraf dist",
|
|
44
|
+
"lint": "eslint --ext .ts src --config eslint.config.mjs",
|
|
45
|
+
"test": "jest",
|
|
46
|
+
"test:update-snapshots": "jest --updateSnapshot",
|
|
47
|
+
"prune": "ts-prune src",
|
|
48
|
+
"prettier": "prettier --write 'src/**/*.ts'"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@pdfme/pdf-lib": "*",
|
|
52
|
+
"fontkit": "^2.0.2"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@pdfme/common": "*",
|
|
56
|
+
"@pdfme/converter": "*",
|
|
57
|
+
"@pdfme/schemas": "*"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@pdfme/common": "latest",
|
|
61
|
+
"@pdfme/schemas": "latest"
|
|
62
|
+
},
|
|
63
|
+
"jest": {
|
|
64
|
+
"resolver": "ts-jest-resolver",
|
|
65
|
+
"setupFilesAfterEnv": [
|
|
66
|
+
"<rootDir>/jest.setup.js"
|
|
67
|
+
],
|
|
68
|
+
"moduleNameMapper": {
|
|
69
|
+
"^@pdfme/schemas/utils$": "<rootDir>/../schemas/src/utils.ts",
|
|
70
|
+
"^.+\\\\.(css|less|scss)$": "identity-obj-proxy"
|
|
71
|
+
},
|
|
72
|
+
"transformIgnorePatterns": [
|
|
73
|
+
"/node_modules/(?!(air-datepicker)/)"
|
|
74
|
+
],
|
|
75
|
+
"moduleFileExtensions": [
|
|
76
|
+
"js",
|
|
77
|
+
"ts"
|
|
78
|
+
],
|
|
79
|
+
"transform": {
|
|
80
|
+
"^.+\\.ts?$": [
|
|
81
|
+
"ts-jest",
|
|
82
|
+
{
|
|
83
|
+
"tsconfig": "tsconfig.esm.json"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"^.+\\.css$": "<rootDir>/__tests__/cssTransform.cjs"
|
|
87
|
+
},
|
|
88
|
+
"testMatch": [
|
|
89
|
+
"**/*.test.ts"
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
"publishConfig": {
|
|
93
|
+
"access": "public"
|
|
94
|
+
}
|
|
95
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const TOOL_NAME = 'pdfme (https://pdfme.com/)';
|
package/src/generate.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import * as pdfLib from '@pdfme/pdf-lib';
|
|
2
|
+
import type { GenerateProps, Schema, PDFRenderProps, Template } from '@pdfme/common';
|
|
3
|
+
import {
|
|
4
|
+
checkGenerateProps,
|
|
5
|
+
getDynamicTemplate,
|
|
6
|
+
isBlankPdf,
|
|
7
|
+
replacePlaceholders,
|
|
8
|
+
pt2mm,
|
|
9
|
+
cloneDeep,
|
|
10
|
+
} from '@pdfme/common';
|
|
11
|
+
import { getDynamicHeightsForTable } from '@pdfme/schemas';
|
|
12
|
+
import {
|
|
13
|
+
insertPage,
|
|
14
|
+
preprocessing,
|
|
15
|
+
postProcessing,
|
|
16
|
+
getEmbedPdfPages,
|
|
17
|
+
validateRequiredFields,
|
|
18
|
+
} from './helper.js';
|
|
19
|
+
|
|
20
|
+
const generate = async (props: GenerateProps): Promise<Uint8Array<ArrayBuffer>> => {
|
|
21
|
+
checkGenerateProps(props);
|
|
22
|
+
const { inputs, template: _template, options = {}, plugins: userPlugins = {} } = props;
|
|
23
|
+
const template = cloneDeep(_template);
|
|
24
|
+
|
|
25
|
+
const basePdf = template.basePdf;
|
|
26
|
+
|
|
27
|
+
if (inputs.length === 0) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
'[@pdfme/generator] inputs should not be empty, pass at least an empty object in the array',
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
validateRequiredFields(template, inputs);
|
|
34
|
+
|
|
35
|
+
const { pdfDoc, renderObj } = await preprocessing({ template, userPlugins });
|
|
36
|
+
|
|
37
|
+
const _cache = new Map<string, unknown>();
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < inputs.length; i += 1) {
|
|
40
|
+
const input = inputs[i];
|
|
41
|
+
|
|
42
|
+
// Get the dynamic template with proper typing
|
|
43
|
+
const dynamicTemplate: Template = await getDynamicTemplate({
|
|
44
|
+
template,
|
|
45
|
+
input,
|
|
46
|
+
options,
|
|
47
|
+
_cache,
|
|
48
|
+
getDynamicHeights: (value, args) => {
|
|
49
|
+
switch (args.schema.type) {
|
|
50
|
+
case 'table':
|
|
51
|
+
return getDynamicHeightsForTable(value, args);
|
|
52
|
+
default:
|
|
53
|
+
return Promise.resolve([args.schema.height]);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const { basePages, embedPdfBoxes } = await getEmbedPdfPages({
|
|
58
|
+
template: dynamicTemplate,
|
|
59
|
+
pdfDoc,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Add proper type assertion for dynamicTemplate.schemas
|
|
63
|
+
const schemas = dynamicTemplate.schemas as Schema[][];
|
|
64
|
+
// Create a type-safe array of schema names without using Set spread which requires downlevelIteration
|
|
65
|
+
const schemaNameSet = new Set<string>();
|
|
66
|
+
schemas.forEach((page: Schema[]) => {
|
|
67
|
+
page.forEach((schema: Schema) => {
|
|
68
|
+
if (schema.name) {
|
|
69
|
+
schemaNameSet.add(schema.name);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
const schemaNames = Array.from(schemaNameSet);
|
|
74
|
+
|
|
75
|
+
for (let j = 0; j < basePages.length; j += 1) {
|
|
76
|
+
const basePage = basePages[j];
|
|
77
|
+
const embedPdfBox = embedPdfBoxes[j];
|
|
78
|
+
|
|
79
|
+
const boundingBoxLeft =
|
|
80
|
+
basePage instanceof pdfLib.PDFEmbeddedPage ? pt2mm(embedPdfBox.mediaBox.x) : 0;
|
|
81
|
+
const boundingBoxBottom =
|
|
82
|
+
basePage instanceof pdfLib.PDFEmbeddedPage ? pt2mm(embedPdfBox.mediaBox.y) : 0;
|
|
83
|
+
|
|
84
|
+
const page = insertPage({ basePage, embedPdfBox, pdfDoc });
|
|
85
|
+
|
|
86
|
+
if (isBlankPdf(basePdf) && basePdf.staticSchema) {
|
|
87
|
+
for (let k = 0; k < basePdf.staticSchema.length; k += 1) {
|
|
88
|
+
const staticSchema = basePdf.staticSchema[k];
|
|
89
|
+
const render = renderObj[staticSchema.type];
|
|
90
|
+
if (!render) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const value = staticSchema.readOnly
|
|
94
|
+
? replacePlaceholders({
|
|
95
|
+
content: staticSchema.content || '',
|
|
96
|
+
variables: { ...input, totalPages: basePages.length, currentPage: j + 1 },
|
|
97
|
+
schemas: schemas, // Use the properly typed schemas variable
|
|
98
|
+
})
|
|
99
|
+
: staticSchema.content || '';
|
|
100
|
+
|
|
101
|
+
staticSchema.position = {
|
|
102
|
+
x: staticSchema.position.x + boundingBoxLeft,
|
|
103
|
+
y: staticSchema.position.y - boundingBoxBottom,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Create properly typed render props for static schema
|
|
107
|
+
const staticRenderProps: PDFRenderProps<Schema> = {
|
|
108
|
+
value,
|
|
109
|
+
schema: staticSchema,
|
|
110
|
+
basePdf,
|
|
111
|
+
pdfLib,
|
|
112
|
+
pdfDoc,
|
|
113
|
+
page,
|
|
114
|
+
options,
|
|
115
|
+
_cache,
|
|
116
|
+
};
|
|
117
|
+
await render(staticRenderProps);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (let l = 0; l < schemaNames.length; l += 1) {
|
|
122
|
+
const name = schemaNames[l];
|
|
123
|
+
const schemaPage = schemas[j] || [];
|
|
124
|
+
const schema = schemaPage.find((s: Schema) => s.name == name);
|
|
125
|
+
if (!schema) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const render = renderObj[schema.type];
|
|
130
|
+
if (!render) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const value: string = schema.readOnly
|
|
134
|
+
? replacePlaceholders({
|
|
135
|
+
content: schema.content || '',
|
|
136
|
+
variables: { ...input, totalPages: basePages.length, currentPage: j + 1 },
|
|
137
|
+
schemas: schemas, // Use the properly typed schemas variable
|
|
138
|
+
})
|
|
139
|
+
: ((input[name] || '') as string);
|
|
140
|
+
|
|
141
|
+
schema.position = {
|
|
142
|
+
x: schema.position.x + boundingBoxLeft,
|
|
143
|
+
y: schema.position.y - boundingBoxBottom,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Create properly typed render props
|
|
147
|
+
const renderProps: PDFRenderProps<Schema> = {
|
|
148
|
+
value,
|
|
149
|
+
schema,
|
|
150
|
+
basePdf,
|
|
151
|
+
pdfLib,
|
|
152
|
+
pdfDoc,
|
|
153
|
+
page,
|
|
154
|
+
options,
|
|
155
|
+
_cache,
|
|
156
|
+
};
|
|
157
|
+
await render(renderProps);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
postProcessing({ pdfDoc, options });
|
|
163
|
+
|
|
164
|
+
return pdfDoc.save();
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default generate;
|
package/src/helper.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import * as fontkit from 'fontkit';
|
|
2
|
+
import {
|
|
3
|
+
Schema,
|
|
4
|
+
Plugins,
|
|
5
|
+
GeneratorOptions,
|
|
6
|
+
Template,
|
|
7
|
+
PDFRenderProps,
|
|
8
|
+
getB64BasePdf,
|
|
9
|
+
isBlankPdf,
|
|
10
|
+
mm2pt,
|
|
11
|
+
pluginRegistry,
|
|
12
|
+
BasePdf,
|
|
13
|
+
} from '@pdfme/common';
|
|
14
|
+
import { builtInPlugins } from '@pdfme/schemas';
|
|
15
|
+
import { PDFPage, PDFDocument, PDFEmbeddedPage, TransformationMatrix } from '@pdfme/pdf-lib';
|
|
16
|
+
import { TOOL_NAME } from './constants.js';
|
|
17
|
+
import type { EmbedPdfBox } from './types.js';
|
|
18
|
+
|
|
19
|
+
export const getEmbedPdfPages = async (arg: { template: Template; pdfDoc: PDFDocument }) => {
|
|
20
|
+
const {
|
|
21
|
+
template: { schemas, basePdf },
|
|
22
|
+
pdfDoc,
|
|
23
|
+
} = arg as { template: { schemas: Schema[][]; basePdf: BasePdf }; pdfDoc: PDFDocument };
|
|
24
|
+
let basePages: (PDFEmbeddedPage | PDFPage)[] = [];
|
|
25
|
+
let embedPdfBoxes: EmbedPdfBox[] = [];
|
|
26
|
+
|
|
27
|
+
if (isBlankPdf(basePdf)) {
|
|
28
|
+
const { width: _width, height: _height } = basePdf;
|
|
29
|
+
const width = mm2pt(_width);
|
|
30
|
+
const height = mm2pt(_height);
|
|
31
|
+
basePages = schemas.map(() => {
|
|
32
|
+
const page = PDFPage.create(pdfDoc);
|
|
33
|
+
page.setSize(width, height);
|
|
34
|
+
return page;
|
|
35
|
+
});
|
|
36
|
+
embedPdfBoxes = schemas.map(() => ({
|
|
37
|
+
mediaBox: { x: 0, y: 0, width, height },
|
|
38
|
+
bleedBox: { x: 0, y: 0, width, height },
|
|
39
|
+
trimBox: { x: 0, y: 0, width, height },
|
|
40
|
+
}));
|
|
41
|
+
} else {
|
|
42
|
+
const willLoadPdf = await getB64BasePdf(basePdf);
|
|
43
|
+
const embedPdf = await PDFDocument.load(willLoadPdf);
|
|
44
|
+
const embedPdfPages = embedPdf.getPages();
|
|
45
|
+
embedPdfBoxes = embedPdfPages.map((p) => ({
|
|
46
|
+
mediaBox: p.getMediaBox(),
|
|
47
|
+
bleedBox: p.getBleedBox(),
|
|
48
|
+
trimBox: p.getTrimBox(),
|
|
49
|
+
}));
|
|
50
|
+
const boundingBoxes = embedPdfPages.map((p) => {
|
|
51
|
+
const { x, y, width, height } = p.getMediaBox();
|
|
52
|
+
return { left: x, bottom: y, right: width, top: height + y };
|
|
53
|
+
});
|
|
54
|
+
const transformationMatrices = embedPdfPages.map(
|
|
55
|
+
() => [1, 0, 0, 1, 0, 0] as TransformationMatrix,
|
|
56
|
+
);
|
|
57
|
+
basePages = await pdfDoc.embedPages(embedPdfPages, boundingBoxes, transformationMatrices);
|
|
58
|
+
}
|
|
59
|
+
return { basePages, embedPdfBoxes };
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const validateRequiredFields = (template: Template, inputs: Record<string, unknown>[]) => {
|
|
63
|
+
(template.schemas as Schema[][]).forEach((schemaPage: Schema[]) =>
|
|
64
|
+
schemaPage.forEach((schema: Schema) => {
|
|
65
|
+
if (schema.required && !schema.readOnly && !inputs.some((input) => input[schema.name])) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`[@pdfme/generator] input for '${schema.name}' is required to generate this PDF`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const preprocessing = async (arg: { template: Template; userPlugins: Plugins }) => {
|
|
75
|
+
const { template, userPlugins } = arg;
|
|
76
|
+
const { schemas, basePdf } = template as { schemas: Schema[][]; basePdf: BasePdf };
|
|
77
|
+
const staticSchema: Schema[] = isBlankPdf(basePdf) ? (basePdf.staticSchema ?? []) : [];
|
|
78
|
+
|
|
79
|
+
const pdfDoc = await PDFDocument.create();
|
|
80
|
+
// @ts-expect-error registerFontkit method is not in type definitions but exists at runtime
|
|
81
|
+
pdfDoc.registerFontkit(fontkit);
|
|
82
|
+
|
|
83
|
+
const plugins = pluginRegistry(
|
|
84
|
+
Object.values(userPlugins).length > 0 ? userPlugins : builtInPlugins,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const schemaTypes = Array.from(
|
|
88
|
+
new Set(
|
|
89
|
+
schemas
|
|
90
|
+
.flatMap((schemaPage: Schema[]) => schemaPage.map((schema: Schema) => schema.type))
|
|
91
|
+
.concat(staticSchema.map((schema: Schema) => schema.type)),
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const renderObj = schemaTypes.reduce(
|
|
96
|
+
(
|
|
97
|
+
acc: Record<
|
|
98
|
+
string,
|
|
99
|
+
(arg: PDFRenderProps<Schema & { [key: string]: unknown }>) => Promise<void> | void
|
|
100
|
+
>,
|
|
101
|
+
type: string,
|
|
102
|
+
) => {
|
|
103
|
+
const plugin = plugins.findByType(type);
|
|
104
|
+
|
|
105
|
+
if (!plugin || !plugin.pdf) {
|
|
106
|
+
throw new Error(`[@pdfme/generator] Plugin or renderer for type ${type} not found.
|
|
107
|
+
Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Use type assertion to handle the pdf function with schema type
|
|
111
|
+
return {
|
|
112
|
+
...acc,
|
|
113
|
+
[type]: plugin.pdf as (
|
|
114
|
+
arg: PDFRenderProps<Schema & { [key: string]: unknown }>,
|
|
115
|
+
) => Promise<void> | void,
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
{} as Record<
|
|
119
|
+
string,
|
|
120
|
+
(arg: PDFRenderProps<Schema & { [key: string]: unknown }>) => Promise<void> | void
|
|
121
|
+
>,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return { pdfDoc, renderObj };
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const postProcessing = (props: { pdfDoc: PDFDocument; options: GeneratorOptions }) => {
|
|
128
|
+
const { pdfDoc, options } = props;
|
|
129
|
+
const {
|
|
130
|
+
author = TOOL_NAME,
|
|
131
|
+
creationDate = new Date(),
|
|
132
|
+
creator = TOOL_NAME,
|
|
133
|
+
keywords = [],
|
|
134
|
+
lang = 'en',
|
|
135
|
+
modificationDate = new Date(),
|
|
136
|
+
producer = TOOL_NAME,
|
|
137
|
+
subject = '',
|
|
138
|
+
title = '',
|
|
139
|
+
} = options;
|
|
140
|
+
pdfDoc.setAuthor(author);
|
|
141
|
+
pdfDoc.setCreationDate(creationDate);
|
|
142
|
+
pdfDoc.setCreator(creator);
|
|
143
|
+
pdfDoc.setKeywords(keywords);
|
|
144
|
+
pdfDoc.setLanguage(lang);
|
|
145
|
+
pdfDoc.setModificationDate(modificationDate);
|
|
146
|
+
pdfDoc.setProducer(producer);
|
|
147
|
+
pdfDoc.setSubject(subject);
|
|
148
|
+
pdfDoc.setTitle(title);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const insertPage = (arg: {
|
|
152
|
+
basePage: PDFEmbeddedPage | PDFPage;
|
|
153
|
+
embedPdfBox: EmbedPdfBox;
|
|
154
|
+
pdfDoc: PDFDocument;
|
|
155
|
+
}) => {
|
|
156
|
+
const { basePage, embedPdfBox, pdfDoc } = arg;
|
|
157
|
+
const size = basePage instanceof PDFEmbeddedPage ? basePage.size() : basePage.getSize();
|
|
158
|
+
const insertedPage =
|
|
159
|
+
basePage instanceof PDFEmbeddedPage
|
|
160
|
+
? pdfDoc.addPage([size.width, size.height])
|
|
161
|
+
: pdfDoc.addPage(basePage);
|
|
162
|
+
|
|
163
|
+
if (basePage instanceof PDFEmbeddedPage) {
|
|
164
|
+
insertedPage.drawPage(basePage);
|
|
165
|
+
const { mediaBox, bleedBox, trimBox } = embedPdfBox;
|
|
166
|
+
insertedPage.setMediaBox(mediaBox.x, mediaBox.y, mediaBox.width, mediaBox.height);
|
|
167
|
+
insertedPage.setBleedBox(bleedBox.x, bleedBox.y, bleedBox.width, bleedBox.height);
|
|
168
|
+
insertedPage.setTrimBox(trimBox.x, trimBox.y, trimBox.width, trimBox.height);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return insertedPage;
|
|
172
|
+
};
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.esm",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"baseUrl": ".",
|
|
6
|
+
"paths": {
|
|
7
|
+
"@pdfme/common": [
|
|
8
|
+
"packages/common/dist/esm/src"
|
|
9
|
+
],
|
|
10
|
+
"@pdfme/schemas": [
|
|
11
|
+
"packages/schemas/dist/esm/src"
|
|
12
|
+
],
|
|
13
|
+
"@pdfme/schemas/utils": [
|
|
14
|
+
"packages/schemas/dist/esm/src/utils"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
}
|