Skip to content

Commit 4a1d507

Browse files
committed
Polish attachments code
1 parent 126a7f3 commit 4a1d507

29 files changed

+353
-221
lines changed

README.md

+50-36
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
- [Copy Pages](#copy-pages)
5252
- [Embed PNG and JPEG Images](#embed-png-and-jpeg-images)
5353
- [Embed PDF Pages](#embed-pdf-pages)
54-
- [Add Attachments](#add-attachments)
5554
- [Embed Font and Measure Text](#embed-font-and-measure-text)
55+
- [Add Attachments](#add-attachments)
5656
- [Set Document Metadata](#set-document-metadata)
5757
- [Read Document Metadata](#read-document-metadata)
5858
- [Draw SVG Paths](#draw-svg-paths)
@@ -360,41 +360,6 @@ const pdfBytes = await pdfDoc.save()
360360
// • Rendered in an <iframe>
361361
```
362362

363-
### Add Attachments
364-
365-
_This example produces [this PDF](assets/pdfs/examples/file_with_attachment.pdf)_ (when [this PDF](assets/pdfs/normal.pdf) is used for the `fileAttachment` variable).
366-
367-
<!-- prettier-ignore -->
368-
```js
369-
import { PDFDocument, rgb } from 'pdf-lib'
370-
371-
// This should be a Uint8Array or ArrayBuffer
372-
// This data can be obtained in a number of different ways
373-
// If your running in a Node environment, you could use fs.readFile()
374-
// In the browser, you could make a fetch() call and use res.arrayBuffer()
375-
const attachmentBytes = ...
376-
377-
// Create a new PDFDocument
378-
const pdfDoc = await PDFDocument.create()
379-
380-
// Add the attachment
381-
await pdfDoc.attach(attachmentBytes, "cool_stuff.pdf", {
382-
mimeType: "application/pdf",
383-
description: "Full of cool stuff",
384-
creationDate: new Date("2019/12/24"),
385-
modificationDate: new Date("2020/01/01"),
386-
checkSum: "D7C816C0E7D35860A9505b2d64C9E3E3"
387-
})
388-
389-
// Serialize the PDFDocument to bytes (a Uint8Array)
390-
const pdfBytes = await pdfDoc.save()
391-
392-
// For example, `pdfBytes` can be:
393-
// • Written to a file in Node
394-
// • Downloaded from the browser
395-
// • Rendered in an <iframe>
396-
```
397-
398363
### Embed Font and Measure Text
399364

400365
`pdf-lib` relies on a sister module to support embedding custom fonts: [`@pdf-lib/fontkit`](https://www.npmjs.com/package/@pdf-lib/fontkit). You must add the `@pdf-lib/fontkit` module to your project and register it using `pdfDoc.registerFontkit(...)` before embedding custom fonts.
@@ -462,6 +427,55 @@ const pdfBytes = await pdfDoc.save()
462427
// • Rendered in an <iframe>
463428
```
464429

430+
### Add Attachments
431+
432+
_This example produces [this PDF](assets/pdfs/examples/add_attachments.pdf)_ (when [this image](assets/images/cat_riding_unicorn.jpg) is used for the `jpgAttachmentBytes` variable and [this PDF](assets/pdfs/us_constitution.pdf) is used for the `pdfAttachmentBytes` variable).
433+
434+
<!-- [Try the JSFiddle demo](https://jsfiddle.net/Hopding/Lyb16ocj/13/) -->
435+
436+
<!-- prettier-ignore -->
437+
```js
438+
import { PDFDocument } from 'pdf-lib'
439+
440+
// These should be Uint8Arrays or ArrayBuffers
441+
// This data can be obtained in a number of different ways
442+
// If your running in a Node environment, you could use fs.readFile()
443+
// In the browser, you could make a fetch() call and use res.arrayBuffer()
444+
const jpgAttachmentBytes = ...
445+
const pdfAttachmentBytes = ...
446+
447+
// Create a new PDFDocument
448+
const pdfDoc = await PDFDocument.create()
449+
450+
// Add the JPG attachment
451+
await pdfDoc.attach(jpgAttachmentBytes, 'cat_riding_unicorn.jpg', {
452+
mimeType: 'image/jpeg',
453+
description: 'Cool cat riding a unicorn! 🦄🐈🕶️',
454+
creationDate: new Date('2019/12/01'),
455+
modificationDate: new Date('2020/04/19'),
456+
})
457+
458+
// Add the PDF attachment
459+
await pdfDoc.attach(pdfAttachmentBytes, 'us_constitution.pdf', {
460+
mimeType: 'application/pdf',
461+
description: 'Constitution of the United States 🇺🇸🦅',
462+
creationDate: new Date('1787/09/17'),
463+
modificationDate: new Date('1992/05/07'),
464+
})
465+
466+
// Add a page with some text
467+
const page = pdfDoc.addPage();
468+
page.drawText('This PDF has two attachments', { x: 135, y: 415 })
469+
470+
// Serialize the PDFDocument to bytes (a Uint8Array)
471+
const pdfBytes = await pdfDoc.save()
472+
473+
// For example, `pdfBytes` can be:
474+
// • Written to a file in Node
475+
// • Downloaded from the browser
476+
// • Rendered in an <iframe>
477+
```
478+
465479
### Set Document Metadata
466480

467481
_This example produces [this PDF](assets/pdfs/examples/set_document_metadata.pdf)_.

apps/deno/index.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { dirname } from 'https://deno.land/[email protected]/path/mod.ts';
22
import { readLines } from 'https://deno.land/[email protected]/io/bufio.ts';
3-
import { defineReader } from './parser.ts';
43

54
import test1 from './tests/test1.ts';
65
import test10 from './tests/test10.ts';
@@ -23,9 +22,14 @@ const promptToContinue = () => {
2322
};
2423

2524
// This needs to be more sophisticated to work on Linux as well.
26-
const openPdf = (path: string, reader: string) => {
25+
const openPdf = (path: string, reader: string = '') => {
2726
if (Deno.build.os === 'darwin') {
2827
Deno.run({ cmd: ['open', '-a', reader, path] });
28+
// Deno.run({ cmd: ['open', '-a', 'Preview', path] });
29+
// Deno.run({ cmd: ['open', '-a', 'Adobe Acrobat', path] });
30+
// Deno.run({ cmd: ['open', '-a', 'Foxit Reader', path] });
31+
// Deno.run({ cmd: ['open', '-a', 'Google Chrome', path] });
32+
// Deno.run({ cmd: ['open', '-a', 'Firefox', path] });
2933
} else if (Deno.build.os === 'windows') {
3034
// Opens with the default PDF Reader, has room for improvment
3135
Deno.run({ cmd: ['start', path] });
@@ -121,8 +125,26 @@ const assets = {
121125

122126
export type Assets = typeof assets;
123127

128+
// This script can be executed with 0, 1, or 2 CLI arguments:
129+
// $ deno index.ts
130+
// $ deno index.ts 3
131+
// $ deno index.ts 'Adobe Acrobat'
132+
// $ deno index.ts 3 'Adobe Acrobat'
133+
const loadCliArgs = (): { testIdx?: number; reader?: string } => {
134+
const { args } = Deno;
135+
136+
if (args.length === 0) return {};
137+
138+
if (args.length === 1) {
139+
if (isFinite(Number(args[0]))) return { testIdx: Number(args[0]) };
140+
else return { reader: args[0] };
141+
}
142+
143+
return { testIdx: Number(args[0]), reader: args[1] };
144+
};
145+
124146
const main = async () => {
125-
const testIdx = Deno.args[0] ? Number(Deno.args[0]) : undefined;
147+
const { testIdx, reader } = loadCliArgs();
126148

127149
// prettier-ignore
128150
const allTests = [
@@ -138,7 +160,7 @@ const main = async () => {
138160
const pdfBytes = await test(assets);
139161
const path = writePdfToTmp(pdfBytes);
140162
console.log(`> PDF file written to: ${path}`);
141-
openPdf(path, defineReader());
163+
openPdf(path, reader);
142164
idx += 1;
143165
await promptToContinue();
144166
console.log();

apps/deno/parser.ts

-20
This file was deleted.

apps/deno/tests/test1.ts

-2
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,11 @@ export default async (assets: Assets) => {
4545

4646
pdfDoc.registerFontkit(fontkit);
4747

48-
4948
pdfDoc.attach(assets.pdfs.with_large_page_count, 'largoPDF.pdf', {
5049
mimeType: 'application/pdf',
5150
description: 'This is a big file',
5251
creationDate: new Date('2006/06/06'),
5352
modificationDate: new Date('2007/07/07'),
54-
checkSum: '59906A0f2FC5BB5983B34B49B011A805',
5553
});
5654

5755
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);

apps/deno/tests/test12.ts

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export default async (_assets: Assets) => {
1111
description: 'This is a file with comments',
1212
creationDate: new Date('2012/12/12'),
1313
modificationDate: new Date('2013/12/11'),
14-
checkSum: 'D1A242A4E0903E882D860ECCA1E52CEA',
1514
});
1615

1716
const page1 = pdfDoc.addPage(PageSizes.Letter);

apps/deno/tests/test3.ts

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export default async (assets: Assets) => {
2222
description: 'This is a great file',
2323
creationDate: new Date('2004/04/04'),
2424
modificationDate: new Date('2005/05/05'),
25-
checkSum: '75D6CC531AF6C03BF154B27B79A11B76',
2625
});
2726

2827
const helveticaFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);

apps/node/index.ts

+28-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { execSync } from 'child_process';
22
import fs from 'fs';
33
import os from 'os';
44
import readline from 'readline';
5-
import { defineReader } from './parser';
65

76
import test1 from './tests/test1';
87
import test10 from './tests/test10';
@@ -28,12 +27,17 @@ const promptToContinue = () =>
2827
new Promise((resolve) => cli.question(prompt, (_answer) => resolve()));
2928

3029
// This needs to be more sophisticated to work on Linux as well.
31-
const openPdf = (path: string, reader: string) => {
30+
const openPdf = (path: string, reader?: string) => {
3231
if (process.platform === 'darwin') {
33-
execSync(`open -a "${reader}" ${path}`);
32+
execSync(`open -a "${reader || 'Preview'}" '${path}'`);
33+
// execSync(`open -a "Preview" '${path}'`);
34+
// execSync(`open -a "Adobe Acrobat" '${path}'`);
35+
// execSync(`open -a "Foxit Reader" '${path}'`);
36+
// execSync(`open -a "Google Chrome" '${path}'`);
37+
// execSync(`open -a "Firefox" '${path}'`);
3438
} else if (process.platform === 'win32') {
3539
// Opens with the default PDF Reader, has room for improvment
36-
execSync(`start ${path}`);
40+
execSync(`start '${path}'`);
3741
} else {
3842
const msg1 = `Note: Automatically opening PDFs currently only works on Macs and Windows. If you're using a Linux machine, please consider contributing to expand support for this feature`;
3943
const msg2 = `(https://github.com/Hopding/pdf-lib/blob/master/apps/node/index.ts#L8-L17)\n`;
@@ -118,9 +122,27 @@ const assets = {
118122

119123
export type Assets = typeof assets;
120124

125+
// This script can be executed with 0, 1, or 2 CLI arguments:
126+
// $ node index.js
127+
// $ node index.js 3
128+
// $ node index.js 'Adobe Acrobat'
129+
// $ node index.js 3 'Adobe Acrobat'
130+
const loadCliArgs = (): { testIdx?: number; reader?: string } => {
131+
const [, , ...args] = process.argv;
132+
133+
if (args.length === 0) return {};
134+
135+
if (args.length === 1) {
136+
if (isFinite(Number(args[0]))) return { testIdx: Number(args[0]) };
137+
else return { reader: args[0] };
138+
}
139+
140+
return { testIdx: Number(args[0]), reader: args[1] };
141+
};
142+
121143
const main = async () => {
122144
try {
123-
const testIdx = process.argv[2] ? Number(process.argv[2]) : undefined;
145+
const { testIdx, reader } = loadCliArgs();
124146

125147
// prettier-ignore
126148
const allTests = [
@@ -137,7 +159,7 @@ const main = async () => {
137159
const path = writePdfToTmp(pdfBytes);
138160
console.log(`> PDF file written to: ${path}`);
139161

140-
openPdf(path, defineReader());
162+
openPdf(path, reader);
141163
idx += 1;
142164
await promptToContinue();
143165
console.log();

apps/node/parser.ts

-20
This file was deleted.

apps/node/tests/test1.ts

-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ export default async (assets: Assets) => {
5050
description: 'This is a big file',
5151
creationDate: new Date('2006/06/06'),
5252
modificationDate: new Date('2007/07/07'),
53-
checkSum: '59906A0f2FC5BB5983B34B49B011A805',
5453
});
5554

5655
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);

apps/node/tests/test12.ts

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export default async (_assets: Assets) => {
1111
description: 'This is a file with comments',
1212
creationDate: new Date('2012/12/12'),
1313
modificationDate: new Date('2013/12/11'),
14-
checkSum: 'D1A242A4E0903E882D860ECCA1E52CEA',
1514
});
1615

1716
const page1 = pdfDoc.addPage(PageSizes.Letter);

apps/node/tests/test3.ts

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export default async (assets: Assets) => {
2121
description: 'This is a great file',
2222
creationDate: new Date('2004/04/04'),
2323
modificationDate: new Date('2005/05/05'),
24-
checkSum: '75D6CC531AF6C03BF154B27B79A11B76',
2524
});
2625

2726
const helveticaFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);

apps/rn/src/tests/test1.js

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export default async () => {
5454
description: 'This is a big file',
5555
creationDate: new Date('2006/06/06'),
5656
modificationDate: new Date('2007/07/07'),
57-
checkSum: '59906A0f2FC5BB5983B34B49B011A805',
5857
},
5958
);
6059

apps/rn/src/tests/test12.js

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export default async () => {
1515
description: 'This is a file with comments',
1616
creationDate: new Date('2012/12/12'),
1717
modificationDate: new Date('2013/12/11'),
18-
checkSum: 'D1A242A4E0903E882D860ECCA1E52CEA',
1918
},
2019
);
2120

apps/rn/src/tests/test3.js

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export default async () => {
2424
description: 'This is a great file',
2525
creationDate: new Date('2004/04/04'),
2626
modificationDate: new Date('2005/05/05'),
27-
checkSum: '75D6CC531AF6C03BF154B27B79A11B76',
2827
});
2928

3029
const helveticaFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);

apps/web/test1.html

-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@
102102
description: 'This is a big file',
103103
creationDate: new Date('2006/06/06'),
104104
modificationDate: new Date('2007/07/07'),
105-
checkSum: '59906A0f2FC5BB5983B34B49B011A805',
106105
},
107106
);
108107

apps/web/test12.html

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
description: 'This is a file with comments',
6363
creationDate: new Date('2012/12/12'),
6464
modificationDate: new Date('2013/12/11'),
65-
checkSum: 'D1A242A4E0903E882D860ECCA1E52CEA',
6665
},
6766
);
6867

apps/web/test3.html

-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
description: 'This is a great file',
7070
creationDate: new Date('2004/04/04'),
7171
modificationDate: new Date('2005/05/05'),
72-
checkSum: '75D6CC531AF6C03BF154B27B79A11B76',
7372
});
7473

7574
const helveticaFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
562 KB
Binary file not shown.

0 commit comments

Comments
 (0)