Files
documenso/packages/lib/server-only/pdf/flatten-annotations.ts
David Nguyen 7f09ba72f4 feat: add envelopes (#2025)
This PR is handles the changes required to support envelopes. The new
envelope editor/signing page will be hidden during release.

The core changes here is to migrate the documents and templates model to
a centralized envelopes model.

Even though Documents and Templates are removed, from the user
perspective they will still exist as we remap envelopes to documents and
templates.
2025-10-14 21:56:36 +11:00

64 lines
1.6 KiB
TypeScript

import { PDFAnnotation, PDFRef } from '@cantoo/pdf-lib';
import {
PDFDict,
type PDFDocument,
PDFName,
drawObject,
popGraphicsState,
pushGraphicsState,
rotateInPlace,
translate,
} from '@cantoo/pdf-lib';
export const flattenAnnotations = (document: PDFDocument) => {
const pages = document.getPages();
for (const page of pages) {
const annotations = page.node.Annots()?.asArray() ?? [];
annotations.forEach((annotation) => {
if (!(annotation instanceof PDFRef)) {
return;
}
const actualAnnotation = page.node.context.lookup(annotation);
if (!(actualAnnotation instanceof PDFDict)) {
return;
}
const pdfAnnot = PDFAnnotation.fromDict(actualAnnotation);
const appearance = pdfAnnot.ensureAP();
// Skip annotations without a normal appearance
if (!appearance.has(PDFName.of('N'))) {
return;
}
const normalAppearance = pdfAnnot.getNormalAppearance();
const rectangle = pdfAnnot.getRectangle();
if (!(normalAppearance instanceof PDFRef)) {
// Not sure how to get the reference to the normal appearance yet
// so we should skip this annotation for now
return;
}
const xobj = page.node.newXObject('FlatAnnot', normalAppearance);
const operators = [
pushGraphicsState(),
translate(rectangle.x, rectangle.y),
...rotateInPlace({ ...rectangle, rotation: 0 }),
drawObject(xobj),
popGraphicsState(),
].filter((op) => !!op);
page.pushOperators(...operators);
page.node.removeAnnot(annotation);
});
}
};