UNPKG

printmaker

Version:

Generate PDF documents and from JavaScript objects

100 lines (89 loc) 2.88 kB
import fontkit from '@pdf-lib/fontkit'; import { PDFDict, PDFDocument, PDFHexString, PDFName } from 'pdf-lib'; import { embedFonts, Font, parseFonts } from './fonts.js'; import { embedImages, Image, parseImages } from './images.js'; import { asArray, asDate, asObject, asString, check, getFrom, Obj, optional, pickDefined, } from './types.js'; export type Document = { fonts: Font[]; images: Image[]; pdfDoc: PDFDocument; }; export async function createDocument(def: Obj): Promise<Document> { const pdfDoc = await PDFDocument.create(); pdfDoc.registerFontkit(fontkit); const fonts = await embedFonts(getFrom(def, 'fonts', parseFonts), pdfDoc); const images = await embedImages(getFrom(def, 'images', parseImages), pdfDoc); setMetadata(getFrom(def, 'info', optional(parseInfo)), pdfDoc); return { fonts, images, pdfDoc }; } type Metadata = { title?: string; subject?: string; keywords?: string[]; author?: string; creationDate?: Date; creator?: string; producer?: string; custom?: Record<string, string>; }; export function parseInfo(input: unknown): Metadata { const obj = asObject(input); const { title, subject, keywords, author, creationDate, creator, producer, ...custom } = obj; return pickDefined({ title: check(title, 'title', optional(asString)), subject: check(subject, 'subject', optional(asString)), keywords: check(keywords, 'keywords', optional(asStringArray)) as string[], author: check(author, 'author', optional(asString)), creationDate: check(creationDate, 'creationDate', optional(asDate)), creator: check(creator, 'creator', optional(asString)), producer: check(producer, 'producer', optional(asString)), custom: parseCustomAttrs(custom), }); } function parseCustomAttrs(custom: Obj): Record<string, string> { if (custom == null || !Object.keys(custom).length) return undefined; Object.entries(asObject(custom)).forEach(([key, value]) => check(value, key, asString)); return custom as Record<string, string>; } function asStringArray(input: unknown): string[] { return asArray(input).map((el, idx) => check(el, `[${idx}]`, asString)); } function setMetadata(info: Metadata, doc: PDFDocument) { if (info?.title) { doc.setTitle(info.title); } if (info?.subject) { doc.setSubject(info.subject); } if (info?.keywords) { doc.setKeywords(info.keywords); } if (info?.author) { doc.setAuthor(info.author); } if (info?.creationDate) { doc.setCreationDate(info.creationDate); } if (info?.creator) { doc.setCreator(info.creator); } if (info?.producer) { doc.setProducer(info.producer); } if (info?.custom) { const dict = (doc as any).getInfoDict() as PDFDict; for (const [key, value] of Object.entries(info.custom)) { dict.set(PDFName.of(key), PDFHexString.fromText(value)); } } }