Skip to content

Commit

Permalink
✨ Support relationship property for embedded files
Browse files Browse the repository at this point in the history
The `AFRelationship` key in the PDF file specification dictionary can be
used to indicate the role of an embedded file in the context of the
document. This key is required for PDF/A documents.

This commit adds support for a `relationship` property of an embedded
file to set it.
  • Loading branch information
ralfstx committed Jan 18, 2025
1 parent 2eb3dc5 commit 069f249
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -603,14 +603,18 @@ archival purposes. Those files can be added to the document using the
representing a file with the following properties:
- `content`: The binary content of the file as a `Uint8Array`.
- `fileName`: The name of the file as it will appear in the
list of attachments in the PDF viewer.
- `fileName`: The name of the file as it will appear in the list of
attachments in the PDF viewer.
- `mimeType`: The MIME type of the file.
- `description` (optional): A brief description of the file's content or
purpose. This information can be displayed to the user in the PDF
viewer.
- `creationDate` (optional): The date and time when the file was created.
- `modificationDate` (optional): The date and time when the file was last
- `creationDate` (optional): The date and time when the file was
created.
- `modificationDate` (optional): The date and time when the file was
last modified.
- `relationship` (optional): A name that specifies the relationship
between the file and the document.
```ts
const document = {
Expand Down
26 changes: 26 additions & 0 deletions src/api/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@ export type DocumentDefinition = {
};
};

/**
* Describes the relationship between the embedded file.
* - `Source`: The embedded file is the source material.
* - `Data`: The embedded file contains data related to the document.
* - `Alternative`: The embedded file is an alternative representation.
* - `Supplement`: The embedded file supplements the document.
* - `EncryptedPayload`: The embedded file is an encrypted payload.
* - `FormData`: The embedded file contains form data.
* - `Schema`: The embedded file contains a schema.
* - `Unspecified`: No specific relationship.
*/
export type FileRelationShip =
| 'Source'
| 'Data'
| 'Alternative'
| 'Supplement'
| 'EncryptedPayload'
| 'FormData'
| 'Schema'
| 'Unspecified';

export type EmbeddedFile = {
/**
* The binary content of the file.
Expand Down Expand Up @@ -133,6 +154,11 @@ export type EmbeddedFile = {
* The date and time when the file was last modified.
*/
modificationDate?: Date;

/**
* The relationship between the file and the PDF document.
*/
relationship?: FileRelationShip;
};

/**
Expand Down
22 changes: 21 additions & 1 deletion src/read-document.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { PDFDocument } from 'pdf-lib';

import type { FileRelationShip } from './api/document.ts';
import type { BoxEdges, Size } from './box.ts';
import { parseEdges } from './box.ts';
import type { FontDef } from './fonts.ts';
Expand Down Expand Up @@ -32,6 +33,7 @@ export type DocumentDefinition = {
description?: string;
creationDate?: Date;
modificationDate?: Date;
relationship?: FileRelationShip;
}[];
onRenderDocument?: (pdfDoc: PDFDocument) => void;
};
Expand Down Expand Up @@ -106,15 +108,33 @@ function readCustomData(input: unknown) {
);
}

/**
* From the PDF-A3 specification, section **3.1. Requirements -
* General**. See:
* https://www.pdfa.org/wp-content/uploads/2018/10/PDF20_AN002-AF.pdf
*/
const readFileRelationship = types.string({
enum: [
'Source',
'Data',
'Alternative',
'Supplement',
'EncryptedPayload',
'FormData',
'Schema',
'Unspecified',
],
});

function readEmbeddedFiles(input: unknown) {
return readObject(input, {
url: optional(types.string()),
content: required(readData),
fileName: required(types.string()),
mimeType: required(types.string()),
description: optional(types.string()),
creationDate: optional(types.date()),
modificationDate: optional(types.date()),
relationship: optional(readFileRelationship),
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/render/render-document.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PDFDict } from 'pdf-lib';
import type { AFRelationship, PDFDict } from 'pdf-lib';
import { PDFDocument, PDFHexString, PDFName } from 'pdf-lib';

import type { Page } from '../page.ts';
Expand All @@ -19,6 +19,7 @@ export async function renderDocument(def: DocumentDefinition, pages: Page[]): Pr
description: file.description,
creationDate: file.creationDate,
modificationDate: file.modificationDate,
afRelationship: file.relationship as AFRelationship | undefined,
});
}

Expand Down

0 comments on commit 069f249

Please sign in to comment.