mirror of
https://github.com/documenso/documenso.git
synced 2026-07-13 22:37:24 +10:00
perf: upgrade @libpdf/core to 0.3.3 and deduplicate font registration (#2598)
Upgrade @libpdf/core from 0.2.12 to 0.3.3, which includes: - WebCrypto SHA-256 replacing pure-JS @noble/hashes (10x signing speedup) - Iterative collectReachableRefs (fixes stack overflow on large PDFs) - Iterative Math.max helpers in xref writer (fixes remaining stack overflow) Extract duplicated FontLibrary.use() calls from render-certificate, render-audit-logs, and insert-field-in-pdf-v2 into a shared ensureFontLibrary() helper with has() guards so fonts are only registered once per process.
This commit is contained in:
@@ -1,9 +1,45 @@
|
||||
import { FieldType } from '@prisma/client';
|
||||
import type { Recipient } from '@prisma/client';
|
||||
import path from 'node:path';
|
||||
import { FontLibrary } from 'skia-canvas';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
|
||||
/**
|
||||
* Ensure all required fonts are registered in the skia-canvas FontLibrary.
|
||||
*
|
||||
* Fonts are registered once per process and retained — calling this multiple
|
||||
* times is a no-op after the first invocation.
|
||||
*/
|
||||
export const ensureFontLibrary = () => {
|
||||
const fontPath = path.join(process.cwd(), 'public/fonts');
|
||||
|
||||
if (!FontLibrary.has('Caveat')) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Caveat']: [path.join(fontPath, 'caveat.ttf')],
|
||||
});
|
||||
}
|
||||
|
||||
if (!FontLibrary.has('Inter')) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Inter']: [path.join(fontPath, 'inter-variablefont_opsz,wght.ttf')],
|
||||
});
|
||||
}
|
||||
|
||||
if (!FontLibrary.has('Noto Sans')) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Noto Sans']: [path.join(fontPath, 'noto-sans.ttf')],
|
||||
['Noto Sans Japanese']: [path.join(fontPath, 'noto-sans-japanese.ttf')],
|
||||
['Noto Sans Chinese']: [path.join(fontPath, 'noto-sans-chinese.ttf')],
|
||||
['Noto Sans Korean']: [path.join(fontPath, 'noto-sans-korean.ttf')],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
type RecipientPlaceholderInfo = {
|
||||
email: string;
|
||||
name: string;
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
import '../konva/skia-backend';
|
||||
|
||||
import Konva from 'konva';
|
||||
import path from 'node:path';
|
||||
import type { Canvas } from 'skia-canvas';
|
||||
import { FontLibrary } from 'skia-canvas';
|
||||
|
||||
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
||||
|
||||
import { renderField } from '../../universal/field-renderer/render-field';
|
||||
import { ensureFontLibrary } from './helpers';
|
||||
|
||||
type InsertFieldInPDFV2Options = {
|
||||
pageWidth: number;
|
||||
@@ -21,16 +20,7 @@ export const insertFieldInPDFV2 = async ({
|
||||
pageHeight,
|
||||
fields,
|
||||
}: InsertFieldInPDFV2Options) => {
|
||||
const fontPath = path.join(process.cwd(), 'public/fonts');
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Caveat']: [path.join(fontPath, 'caveat.ttf')],
|
||||
['Noto Sans']: [path.join(fontPath, 'noto-sans.ttf')],
|
||||
['Noto Sans Japanese']: [path.join(fontPath, 'noto-sans-japanese.ttf')],
|
||||
['Noto Sans Chinese']: [path.join(fontPath, 'noto-sans-chinese.ttf')],
|
||||
['Noto Sans Korean']: [path.join(fontPath, 'noto-sans-korean.ttf')],
|
||||
});
|
||||
ensureFontLibrary();
|
||||
|
||||
let stage: Konva.Stage | null = new Konva.Stage({ width: pageWidth, height: pageHeight });
|
||||
let layer: Konva.Layer | null = new Konva.Layer();
|
||||
|
||||
@@ -9,7 +9,6 @@ import { DateTime } from 'luxon';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import type { Canvas } from 'skia-canvas';
|
||||
import { FontLibrary } from 'skia-canvas';
|
||||
import { Image as SkiaImage } from 'skia-canvas';
|
||||
import { match } from 'ts-pattern';
|
||||
import { P } from 'ts-pattern';
|
||||
@@ -21,6 +20,7 @@ import { RECIPIENT_ROLES_DESCRIPTION } from '../../constants/recipient-roles';
|
||||
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
|
||||
import type { TDocumentAuditLog } from '../../types/document-audit-logs';
|
||||
import { formatDocumentAuditLogAction } from '../../utils/document-audit-logs';
|
||||
import { ensureFontLibrary } from './helpers';
|
||||
|
||||
export type AuditLogRecipient = {
|
||||
id: number;
|
||||
@@ -575,13 +575,7 @@ export async function renderAuditLogs({
|
||||
i18n,
|
||||
hidePoweredBy,
|
||||
}: GenerateAuditLogsOptions) {
|
||||
const fontPath = path.join(process.cwd(), 'public/fonts');
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Caveat']: [path.join(fontPath, 'caveat.ttf')],
|
||||
['Inter']: [path.join(fontPath, 'inter-variablefont_opsz,wght.ttf')],
|
||||
});
|
||||
ensureFontLibrary();
|
||||
|
||||
const minimumMargin = 10;
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import { DateTime } from 'luxon';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import type { Canvas } from 'skia-canvas';
|
||||
import { FontLibrary } from 'skia-canvas';
|
||||
import { Image as SkiaImage } from 'skia-canvas';
|
||||
import { UAParser } from 'ua-parser-js';
|
||||
import { renderSVG } from 'uqr';
|
||||
@@ -22,6 +21,7 @@ import {
|
||||
} from '../../constants/recipient-roles';
|
||||
import type { TDocumentAuditLogBaseSchema } from '../../types/document-audit-logs';
|
||||
import { svgToPng } from '../../utils/images/svg-to-png';
|
||||
import { ensureFontLibrary } from './helpers';
|
||||
|
||||
type ColumnWidths = [number, number, number];
|
||||
|
||||
@@ -724,13 +724,7 @@ export async function renderCertificate({
|
||||
pageWidth,
|
||||
pageHeight,
|
||||
}: GenerateCertificateOptions) {
|
||||
const fontPath = path.join(process.cwd(), 'public/fonts');
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
FontLibrary.use({
|
||||
['Caveat']: [path.join(fontPath, 'caveat.ttf')],
|
||||
['Inter']: [path.join(fontPath, 'inter-variablefont_opsz,wght.ttf')],
|
||||
});
|
||||
ensureFontLibrary();
|
||||
|
||||
const minimumMargin = 10;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user