Skip to content

Commit 543cbd9

Browse files
committed
feat: add pdfkit subsets mixin
1 parent 685890b commit 543cbd9

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

packages/pdfkit/src/document.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/*
2+
PDFDocument - represents an entire PDF document
3+
By Devon Govett
4+
*/
5+
16
import stream from 'stream';
27
import PDFObject from './object';
38
import PDFReference from './reference';
@@ -15,11 +20,12 @@ import MarkingsMixin from './mixins/markings';
1520
import AcroFormMixin from './mixins/acroform';
1621
import AttachmentsMixin from './mixins/attachments';
1722
import MetadataMixin from './mixins/metadata';
23+
import SubsetMixin from './mixins/subsets';
1824
import capitalize from './utils/capitalize';
1925

2026
class PDFDocument extends stream.Readable {
2127
constructor(options = {}) {
22-
super();
28+
super(options);
2329
this.options = options;
2430

2531
// PDF version
@@ -93,6 +99,7 @@ class PDFDocument extends stream.Readable {
9399
this.initText();
94100
this.initImages();
95101
this.initOutline();
102+
this.initSubset(options);
96103
// this.initMarkings(options)
97104

98105
// Initialize the metadata
@@ -267,6 +274,10 @@ class PDFDocument extends stream.Readable {
267274
this.endOutline();
268275
// this.endMarkings();
269276

277+
if (this.subset) {
278+
this.endSubset();
279+
}
280+
270281
this._root.end();
271282
this._root.data.Pages.end();
272283
this._root.data.Names.end();
@@ -370,5 +381,6 @@ mixin(OutlineMixin);
370381
mixin(MarkingsMixin);
371382
mixin(AcroFormMixin);
372383
mixin(AttachmentsMixin);
384+
mixin(SubsetMixin);
373385

374386
export default PDFDocument;

packages/pdfkit/src/mixins/pdfa.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import fs from 'fs';
2+
3+
export default {
4+
initPDFA(pSubset) {
5+
if (pSubset.charAt(pSubset.length - 3) === '-') {
6+
this.subset_conformance = pSubset
7+
.charAt(pSubset.length - 1)
8+
.toUpperCase();
9+
this.subset = parseInt(pSubset.charAt(pSubset.length - 2));
10+
} else {
11+
// Default to Basic conformance when user doesn't specify
12+
this.subset_conformance = 'B';
13+
this.subset = parseInt(pSubset.charAt(pSubset.length - 1));
14+
}
15+
},
16+
17+
endSubset() {
18+
this._addPdfaMetadata();
19+
this._addColorOutputIntent();
20+
},
21+
22+
_addColorOutputIntent() {
23+
const iccProfile = fs.readFileSync(
24+
`${__dirname}/data/sRGB_IEC61966_2_1.icc`
25+
);
26+
27+
const colorProfileRef = this.ref({
28+
Length: iccProfile.length,
29+
N: 3
30+
});
31+
colorProfileRef.write(iccProfile);
32+
colorProfileRef.end();
33+
34+
const intentRef = this.ref({
35+
Type: 'OutputIntent',
36+
S: 'GTS_PDFA1',
37+
Info: new String('sRGB IEC61966-2.1'),
38+
OutputConditionIdentifier: new String('sRGB IEC61966-2.1'),
39+
DestOutputProfile: colorProfileRef
40+
});
41+
intentRef.end();
42+
43+
this._root.data.OutputIntents = [intentRef];
44+
},
45+
46+
_getPdfaid() {
47+
return `
48+
<rdf:Description xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" rdf:about="">
49+
<pdfaid:part>${this.subset}</pdfaid:part>
50+
<pdfaid:conformance>${this.subset_conformance}</pdfaid:conformance>
51+
</rdf:Description>
52+
`;
53+
},
54+
55+
_addPdfaMetadata() {
56+
this.appendXML(this._getPdfaid());
57+
}
58+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export default {
2+
initPDFUA() {
3+
this.subset = 1;
4+
},
5+
6+
endSubset() {
7+
this._addPdfuaMetadata();
8+
},
9+
10+
_addPdfuaMetadata() {
11+
this.appendXML(this._getPdfuaid());
12+
},
13+
14+
_getPdfuaid() {
15+
return `
16+
<rdf:Description xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/" rdf:about="">
17+
<pdfuaid:part>${this.subset}</pdfuaid:part>
18+
</rdf:Description>
19+
`;
20+
}
21+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import PDFA from './pdfa';
2+
import PDFUA from './pdfua';
3+
4+
export default {
5+
_importSubset(subset) {
6+
Object.assign(this, subset);
7+
},
8+
9+
initSubset(options) {
10+
switch (options.subset) {
11+
case 'PDF/A-1':
12+
case 'PDF/A-1a':
13+
case 'PDF/A-1b':
14+
case 'PDF/A-2':
15+
case 'PDF/A-2a':
16+
case 'PDF/A-2b':
17+
case 'PDF/A-3':
18+
case 'PDF/A-3a':
19+
case 'PDF/A-3b':
20+
this._importSubset(PDFA);
21+
this.initPDFA(options.subset);
22+
break;
23+
case 'PDF/UA':
24+
this._importSubset(PDFUA);
25+
this.initPDFUA();
26+
break;
27+
}
28+
}
29+
};

0 commit comments

Comments
 (0)