Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New basePdf type and Support adding new pages to template #394

Merged
merged 20 commits into from Jan 3, 2024
Merged
3 changes: 3 additions & 0 deletions packages/common/src/helper.ts
Expand Up @@ -9,6 +9,7 @@ import {
DesignerProps as DesignerPropsSchema,
GenerateProps as GeneratePropsSchema,
UIProps as UIPropsSchema,
BlankPdf,
} from './schema.js';
import {
MM_TO_PT_RATIO,
Expand Down Expand Up @@ -98,6 +99,8 @@ export const getB64BasePdf = (basePdf: BasePdf) => {
return basePdf as string;
};

export const isBlankPdf = (basePdf: BasePdf) => BlankPdf.safeParse(basePdf).success;

const getByteString = (base64: string) => Buffer.from(base64, 'base64').toString('binary');

export const b64toUint8Array = (base64: string) => {
Expand Down
4 changes: 3 additions & 1 deletion packages/common/src/index.ts
Expand Up @@ -48,7 +48,8 @@ import {
pt2mm,
pt2px,
isHexValid,
getInputFromTemplate
getInputFromTemplate,
isBlankPdf,
} from './helper.js';

export {
Expand All @@ -67,6 +68,7 @@ export {
pt2px,
isHexValid,
getInputFromTemplate,
isBlankPdf,
checkFont,
checkInputs,
checkUIOptions,
Expand Down
23 changes: 14 additions & 9 deletions packages/common/src/schema.ts
Expand Up @@ -80,16 +80,13 @@ export const SchemaForUI = Schema.merge(SchemaForUIAdditionalInfo);

const ArrayBufferSchema: z.ZodSchema<ArrayBuffer> = z.any().refine((v) => v instanceof ArrayBuffer);
const Uint8ArraySchema: z.ZodSchema<Uint8Array> = z.any().refine((v) => v instanceof Uint8Array);
export const BlankPdf = z.object({
width: z.number(),
height: z.number(),
padding: z.array(z.number()).length(4).optional(),
});

export const Font = z.record(
z.object({
data: z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]),
fallback: z.boolean().optional(),
subset: z.boolean().optional(),
})
);

export const BasePdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]);
export const BasePdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema, BlankPdf]);

export const Template = z
.object({
Expand All @@ -100,6 +97,14 @@ export const Template = z

export const Inputs = z.array(z.record(z.string())).min(1);

export const Font = z.record(
z.object({
data: z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]),
fallback: z.boolean().optional(),
subset: z.boolean().optional(),
})
);

const CommonOptions = z.object({ font: Font.optional() }).passthrough();

const CommonProps = z.object({
Expand Down
Binary file modified packages/generator/__tests__/assets/pdfs/assert/pet.pdf
Binary file not shown.
5 changes: 4 additions & 1 deletion packages/generator/__tests__/assets/templates/pet.json
Expand Up @@ -404,7 +404,10 @@
}
}
],
"basePdf": "data:application/pdf;base64,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",
"basePdf": {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main part of what I did in this PR is that I made it so that we can set it with a new type called BlankPdf instead of PDF data in basePdf.

"width": 210,
"height": 297
},
"columns": [
"name",
"subtitle",
Expand Down
14 changes: 5 additions & 9 deletions packages/generator/src/generate.ts
@@ -1,7 +1,7 @@
import * as pdfLib from '@pdfme/pdf-lib';
import type { GenerateProps } from '@pdfme/common';
import { checkGenerateProps } from '@pdfme/common';
import { drawEmbeddedPage, preprocessing, postProcessing } from './helper.js';
import { insertPage, preprocessing, postProcessing } from './helper.js';

const generate = async (props: GenerateProps) => {
checkGenerateProps(props);
Expand All @@ -11,7 +11,7 @@ const generate = async (props: GenerateProps) => {
throw new Error('inputs should not be empty');
}

const { pdfDoc, embeddedPages, embedPdfBoxes, renderObj } = await preprocessing({
const { pdfDoc, basePages, embedPdfBoxes, renderObj } = await preprocessing({
template,
userPlugins,
});
Expand All @@ -21,14 +21,10 @@ const generate = async (props: GenerateProps) => {
const _cache = new Map();
for (let i = 0; i < inputs.length; i += 1) {
const inputObj = inputs[i];
for (let j = 0; j < embeddedPages.length; j += 1) {
const embeddedPage = embeddedPages[j];
const { width: pageWidth, height: pageHeight } = embeddedPage;
for (let j = 0; j < basePages.length; j += 1) {
const basePage = basePages[j];
const embedPdfBox = embedPdfBoxes[j];

const page = pdfDoc.addPage([pageWidth, pageHeight]);

drawEmbeddedPage({ page, embeddedPage, embedPdfBox });
const page = insertPage({ basePage, embedPdfBox, pdfDoc });
for (let l = 0; l < keys.length; l += 1) {
const key = keys[l];
const schemaObj = template.schemas[j];
Expand Down
125 changes: 75 additions & 50 deletions packages/generator/src/helper.ts
@@ -1,68 +1,76 @@
import * as fontkit from 'fontkit';
import * as pdfLib from '@pdfme/pdf-lib';
import type { GeneratorOptions, Template, PDFRenderProps, Plugin } from '@pdfme/common';
import type { Schema, Plugins } from '@pdfme/common';
import type {
Schema,
Plugins,
GeneratorOptions,
Template,
PDFRenderProps,
Plugin,
} from '@pdfme/common';
import { builtInPlugins } from '@pdfme/schemas';
import { PDFPage, PDFDocument, PDFEmbeddedPage, TransformationMatrix } from '@pdfme/pdf-lib';
import { getB64BasePdf, BasePdf } from '@pdfme/common';
import { getB64BasePdf, BasePdf, isBlankPdf, mm2pt } from '@pdfme/common';
hand-dot marked this conversation as resolved.
Show resolved Hide resolved
import { TOOL_NAME } from './constants.js';
import type { EmbedPdfBox } from './types';

export const getEmbeddedPagesAndEmbedPdfBoxes = async (arg: {
const getBasePagesAndEmbedPdfBoxes = async (arg: {
template: Template;
pdfDoc: PDFDocument;
basePdf: BasePdf;
}) => {
const { pdfDoc, basePdf } = arg;
let embeddedPages: PDFEmbeddedPage[] = [];
const {
template: { schemas },
pdfDoc,
basePdf,
} = arg;
let basePages: (PDFEmbeddedPage | PDFPage)[] = [];
let embedPdfBoxes: EmbedPdfBox[] = [];
const willLoadPdf = typeof basePdf === 'string' ? await getB64BasePdf(basePdf) : basePdf;
const embedPdf = await PDFDocument.load(willLoadPdf);
const embedPdfPages = embedPdf.getPages();

embedPdfBoxes = embedPdfPages.map((p) => ({
mediaBox: p.getMediaBox(),
bleedBox: p.getBleedBox(),
trimBox: p.getTrimBox(),
}));

const boundingBoxes = embedPdfPages.map((p) => {
const { x, y, width, height } = p.getMediaBox();

return { left: x, bottom: y, right: width, top: height + y };
});

const transformationMatrices = embedPdfPages.map(
() => [1, 0, 0, 1, 0, 0] as TransformationMatrix
);

embeddedPages = await pdfDoc.embedPages(embedPdfPages, boundingBoxes, transformationMatrices);

return { embeddedPages, embedPdfBoxes };
};

export const drawEmbeddedPage = (arg: {
page: PDFPage;
embeddedPage: PDFEmbeddedPage;
embedPdfBox: EmbedPdfBox;
}) => {
const { page, embeddedPage, embedPdfBox } = arg;
page.drawPage(embeddedPage);
const { mediaBox: mb, bleedBox: bb, trimBox: tb } = embedPdfBox;
page.setMediaBox(mb.x, mb.y, mb.width, mb.height);
page.setBleedBox(bb.x, bb.y, bb.width, bb.height);
page.setTrimBox(tb.x, tb.y, tb.width, tb.height);
if (isBlankPdf(basePdf)) {
const { width: _width, height: _height } = basePdf as { width: number; height: number };
const width = mm2pt(_width);
const height = mm2pt(_height);
basePages = schemas.map(() => {
const page = PDFPage.create(pdfDoc);
page.setSize(width, height);
return page;
});
embedPdfBoxes = schemas.map(() => ({
mediaBox: { x: 0, y: 0, width, height },
bleedBox: { x: 0, y: 0, width, height },
trimBox: { x: 0, y: 0, width, height },
}));
} else {
const willLoadPdf = typeof basePdf === 'string' ? await getB64BasePdf(basePdf) : basePdf;
const embedPdf = await PDFDocument.load(willLoadPdf as ArrayBuffer | Uint8Array | string);
const embedPdfPages = embedPdf.getPages();
embedPdfBoxes = embedPdfPages.map((p) => ({
mediaBox: p.getMediaBox(),
bleedBox: p.getBleedBox(),
trimBox: p.getTrimBox(),
}));
const boundingBoxes = embedPdfPages.map((p) => {
const { x, y, width, height } = p.getMediaBox();
return { left: x, bottom: y, right: width, top: height + y };
});
const transformationMatrices = embedPdfPages.map(
() => [1, 0, 0, 1, 0, 0] as TransformationMatrix
);
basePages = await pdfDoc.embedPages(embedPdfPages, boundingBoxes, transformationMatrices);
}
return { basePages, embedPdfBoxes };
};

export const preprocessing = async (arg: { template: Template; userPlugins: Plugins }) => {
const { template, userPlugins } = arg;
const { basePdf, schemas } = template;

const pdfDoc = await pdfLib.PDFDocument.create();
const pdfDoc = await PDFDocument.create();
// @ts-ignore
pdfDoc.registerFontkit(fontkit);

const pagesAndBoxes = await getEmbeddedPagesAndEmbedPdfBoxes({ pdfDoc, basePdf });
const { embeddedPages, embedPdfBoxes } = pagesAndBoxes;
const basePagesAndBoxes = await getBasePagesAndEmbedPdfBoxes({ template, pdfDoc, basePdf });
const { basePages, embedPdfBoxes } = basePagesAndBoxes;

const pluginValues = (
Object.values(userPlugins).length > 0
Expand All @@ -84,13 +92,10 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
return { ...acc, [type]: render.pdf };
}, {} as Record<string, (arg: PDFRenderProps<Schema>) => Promise<void> | void>);

return { pdfDoc, embeddedPages, embedPdfBoxes, renderObj };
return { pdfDoc, basePages, embedPdfBoxes, renderObj };
};

export const postProcessing = (props: {
pdfDoc: pdfLib.PDFDocument;
options: GeneratorOptions;
}) => {
export const postProcessing = (props: { pdfDoc: PDFDocument; options: GeneratorOptions }) => {
const { pdfDoc, options } = props;
const {
author = TOOL_NAME,
Expand All @@ -113,3 +118,23 @@ export const postProcessing = (props: {
pdfDoc.setSubject(subject);
pdfDoc.setTitle(title);
};

export const insertPage = (arg: {
basePage: PDFEmbeddedPage | PDFPage;
embedPdfBox: EmbedPdfBox;
pdfDoc: PDFDocument;
}) => {
const { basePage, embedPdfBox, pdfDoc } = arg;
const size = basePage instanceof PDFEmbeddedPage ? basePage.size() : basePage.getSize();
const insertedPage = pdfDoc.addPage([size.width, size.height]);

if (basePage instanceof PDFEmbeddedPage) {
insertedPage.drawPage(basePage);
const { mediaBox, bleedBox, trimBox } = embedPdfBox;
insertedPage.setMediaBox(mediaBox.x, mediaBox.y, mediaBox.width, mediaBox.height);
insertedPage.setBleedBox(bleedBox.x, bleedBox.y, bleedBox.width, bleedBox.height);
insertedPage.setTrimBox(trimBox.x, trimBox.y, trimBox.width, trimBox.height);
}

return insertedPage;
};
6 changes: 3 additions & 3 deletions packages/ui/src/components/Designer/Canvas/index.tsx
Expand Up @@ -155,6 +155,7 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
}, [pageCursor, schemasList, prevSchemas]);

const onDrag = ({ target, left, top }: OnDrag) => {
// TODO basePdfのpaddingを考慮できていない
target.style.left = `${left < 0 ? 0 : left}px`;
target.style.top = `${top < 0 ? 0 : top}px`;
};
Expand Down Expand Up @@ -383,9 +384,8 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
changeSchemas([{ key: 'content', value, schemaId: schema.id }]);
}}
stopEditing={() => setEditing(false)}
outline={`1px ${hoveringSchemaId === schema.id ? 'solid' : 'dashed'} ${
schema.readOnly ? 'transparent' : token.colorPrimary
}`}
outline={`1px ${hoveringSchemaId === schema.id ? 'solid' : 'dashed'} ${schema.readOnly && hoveringSchemaId !== schema.id ? 'transparent' : token.colorPrimary
}`}
scale={scale}
/>
)}
Expand Down
13 changes: 10 additions & 3 deletions packages/ui/src/helper.ts
Expand Up @@ -13,6 +13,7 @@ import {
SchemaForUI,
Schema,
Size,
isBlankPdf,
} from '@pdfme/common';
import { RULER_HEIGHT } from './constants.js';

Expand Down Expand Up @@ -267,9 +268,15 @@ const sortSchemasList = (template: Template): SchemaForUI[][] => {
export const templateSchemas2SchemasList = async (_template: Template) => {
const template = cloneDeep(_template);
const sortedSchemasList = sortSchemasList(template);
const basePdf = await getB64BasePdf(template.basePdf);
const pdfBlob = b64toBlob(basePdf);
const pageSizes = await getPdfPageSizes(pdfBlob);
let pageSizes: { width: number; height: number }[] = [];
if (isBlankPdf(template.basePdf)) {
pageSizes = template.schemas.map(() => template.basePdf as { width: number; height: number });
} else {
const basePdf = await getB64BasePdf(template.basePdf);
const pdfBlob = b64toBlob(basePdf);
pageSizes = await getPdfPageSizes(pdfBlob);
}

const ssl = sortedSchemasList.length;
const psl = pageSizes.length;
const schemasList = (
Expand Down
40 changes: 32 additions & 8 deletions packages/ui/src/hooks.ts
@@ -1,5 +1,13 @@
import { RefObject, useRef, useState, useCallback, useEffect } from 'react';
import { ZOOM, Template, Size, getB64BasePdf, SchemaForUI, ChangeSchemas } from '@pdfme/common';
import {
ZOOM,
Template,
Size,
getB64BasePdf,
SchemaForUI,
ChangeSchemas,
isBlankPdf,
} from '@pdfme/common';

import {
fmtTemplate,
Expand Down Expand Up @@ -36,21 +44,37 @@ export const useUIPreProcessor = ({ template, size, zoomLevel }: UIPreProcessorP
const [error, setError] = useState<Error | null>(null);

const init = async (prop: { template: Template; size: Size }) => {
const { template, size } = prop;
const _basePdf = await getB64BasePdf(template.basePdf);
const pdfBlob = b64toBlob(_basePdf);
const _pageSizes = await getPdfPageSizes(pdfBlob);
const paperWidth = _pageSizes[0].width * ZOOM;
const paperHeight = _pageSizes[0].height * ZOOM;
const _backgrounds = await pdf2Pngs(pdfBlob, paperWidth);
const {
template: { basePdf, schemas },
size,
} = prop;
let paperWidth, paperHeight, _backgrounds, _pageSizes;

if (isBlankPdf(basePdf)) {
const { width, height } = basePdf as { width: number; height: number };
paperWidth = width * ZOOM;
paperHeight = height * ZOOM;
_backgrounds = schemas.map(
() =>
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+P///38ACfsD/QVDRcoAAAAASUVORK5CYII='
);
_pageSizes = [{ width, height }];
} else {
const _basePdf = await getB64BasePdf(basePdf);
const pdfBlob = b64toBlob(_basePdf);
_pageSizes = await getPdfPageSizes(pdfBlob);
paperWidth = _pageSizes[0].width * ZOOM;
paperHeight = _pageSizes[0].height * ZOOM;
_backgrounds = await pdf2Pngs(pdfBlob, paperWidth);
}
const _scale = Math.min(
getScale(size.width, paperWidth),
getScale(size.height - RULER_HEIGHT, paperHeight)
);

return { backgrounds: _backgrounds, pageSizes: _pageSizes, scale: _scale };
};

useEffect(() => {
init({ template, size })
.then(({ pageSizes, scale, backgrounds }) => {
Expand Down
1 change: 1 addition & 0 deletions playground/src/Designer.tsx
Expand Up @@ -59,6 +59,7 @@ function App() {
}

const onChangeBasePDF = (e: React.ChangeEvent<HTMLInputElement>) => {
// TODO 修正 size指定で渡せるような仕組みを作る。じゃないとページ埋め込みのサンプルしか見せられない
if (e.target && e.target.files) {
readFile(e.target.files[0], "dataURL").then(async (basePdf) => {
if (designer.current) {
Expand Down