diff --git a/docker/development/compose.yml b/docker/development/compose.yml index 6077668ac..3922ce614 100644 --- a/docker/development/compose.yml +++ b/docker/development/compose.yml @@ -40,43 +40,6 @@ services: entrypoint: sh command: -c 'mkdir -p /data/documenso && minio server /data --console-address ":9001" --address ":9002"' - triggerdotdev: - image: ghcr.io/triggerdotdev/trigger.dev:latest - container_name: triggerdotdev - environment: - - LOGIN_ORIGIN=http://localhost:3030 - - APP_ORIGIN=http://localhost:3030 - - PORT=3030 - - REMIX_APP_PORT=3030 - - MAGIC_LINK_SECRET=secret - - SESSION_SECRET=secret - - ENCRYPTION_KEY=deadbeefcafefeed - - DATABASE_URL=postgresql://trigger:password@triggerdotdev_database:5432/trigger - - DIRECT_URL=postgresql://trigger:password@triggerdotdev_database:5432/trigger - - RUNTIME_PLATFORM=docker-compose - ports: - - 3030:3030 - depends_on: - - triggerdotdev_database - - triggerdotdev_database: - container_name: triggerdotdev_database - image: postgres:15 - volumes: - - triggerdotdev_database:/var/lib/postgresql/data - healthcheck: - test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER}'] - interval: 10s - timeout: 5s - retries: 5 - environment: - - POSTGRES_USER=trigger - - POSTGRES_PASSWORD=password - - POSTGRES_DB=trigger - ports: - - 54321:5432 - volumes: minio: documenso_database: - triggerdotdev_database: diff --git a/packages/lib/server-only/document/seal-document.ts b/packages/lib/server-only/document/seal-document.ts index 507f6ec19..f28274e6d 100644 --- a/packages/lib/server-only/document/seal-document.ts +++ b/packages/lib/server-only/document/seal-document.ts @@ -128,7 +128,7 @@ export const sealDocument = async ({ // Normalize and flatten layers that could cause issues with the signature normalizeSignatureAppearances(doc); - flattenForm(doc); + await flattenForm(doc); flattenAnnotations(doc); // Add rejection stamp if the document is rejected @@ -153,7 +153,7 @@ export const sealDocument = async ({ } // Re-flatten post-insertion to handle fields that create arcoFields - flattenForm(doc); + await flattenForm(doc); const pdfBytes = await doc.save(); diff --git a/packages/lib/server-only/pdf/flatten-form.ts b/packages/lib/server-only/pdf/flatten-form.ts index 0970309e8..ab5b17a1c 100644 --- a/packages/lib/server-only/pdf/flatten-form.ts +++ b/packages/lib/server-only/pdf/flatten-form.ts @@ -1,3 +1,4 @@ +import fontkit from '@pdf-lib/fontkit'; import type { PDFField, PDFWidgetAnnotation } from 'pdf-lib'; import { PDFCheckBox, @@ -13,6 +14,8 @@ import { translate, } from 'pdf-lib'; +import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; + export const removeOptionalContentGroups = (document: PDFDocument) => { const context = document.context; const catalog = context.lookup(context.trailerInfo.Root); @@ -21,12 +24,20 @@ export const removeOptionalContentGroups = (document: PDFDocument) => { } }; -export const flattenForm = (document: PDFDocument) => { +export const flattenForm = async (document: PDFDocument) => { removeOptionalContentGroups(document); const form = document.getForm(); - form.updateFieldAppearances(); + const fontNoto = await fetch(`${NEXT_PUBLIC_WEBAPP_URL()}/fonts/noto-sans.ttf`).then( + async (res) => res.arrayBuffer(), + ); + + document.registerFontkit(fontkit); + + const font = await document.embedFont(fontNoto); + + form.updateFieldAppearances(font); for (const field of form.getFields()) { for (const widget of field.acroField.getWidgets()) { diff --git a/packages/lib/server-only/pdf/insert-field-in-pdf.ts b/packages/lib/server-only/pdf/insert-field-in-pdf.ts index 8db5abcfe..a89a3c3f9 100644 --- a/packages/lib/server-only/pdf/insert-field-in-pdf.ts +++ b/packages/lib/server-only/pdf/insert-field-in-pdf.ts @@ -1,8 +1,15 @@ // https://github.com/Hopding/pdf-lib/issues/20#issuecomment-412852821 import fontkit from '@pdf-lib/fontkit'; import { FieldType } from '@prisma/client'; -import type { PDFDocument, PDFFont } from 'pdf-lib'; -import { RotationTypes, TextAlignment, degrees, radiansToDegrees, rgb } from 'pdf-lib'; +import type { PDFDocument, PDFFont, PDFTextField } from 'pdf-lib'; +import { + RotationTypes, + TextAlignment, + degrees, + radiansToDegrees, + rgb, + setFontAndSize, +} from 'pdf-lib'; import { P, match } from 'ts-pattern'; import { @@ -442,6 +449,10 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu adjustedFieldY = adjustedPosition.yPos; } + // Set properties for the text field + setTextFieldFontSize(textField, font, fontSize); + textField.setText(textToInsert); + // Set the position and size of the text field textField.addToPage(page, { x: adjustedFieldX, @@ -450,6 +461,8 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu height: adjustedFieldHeight, rotate: degrees(pageRotationInDegrees), + font, + // Hide borders. borderWidth: 0, borderColor: undefined, @@ -457,10 +470,6 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu ...(isDebugMode ? { borderWidth: 1, borderColor: rgb(0, 0, 1) } : {}), }); - - // Set properties for the text field - textField.setFontSize(fontSize); - textField.setText(textToInsert); }); return pdf; @@ -629,3 +638,21 @@ function breakLongString(text: string, maxWidth: number, font: PDFFont, fontSize return lines.join('\n'); } + +const setTextFieldFontSize = (textField: PDFTextField, font: PDFFont, fontSize: number) => { + textField.defaultUpdateAppearances(font); + textField.updateAppearances(font); + + try { + textField.setFontSize(fontSize); + } catch (err) { + let da = textField.acroField.getDefaultAppearance() ?? ''; + + da += `\n ${setFontAndSize(font.name, fontSize)}`; + + textField.acroField.setDefaultAppearance(da); + } + + textField.defaultUpdateAppearances(font); + textField.updateAppearances(font); +};