Skip to content

Commit

Permalink
feat: generate document ID (#1894)
Browse files Browse the repository at this point in the history
  • Loading branch information
diegomura committed Jun 18, 2022
1 parent 035d3f8 commit 9527fe4
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-mirrors-warn.md
@@ -0,0 +1,5 @@
---
'@react-pdf/pdfkit': patch
---

feat: generate document ID
4 changes: 3 additions & 1 deletion packages/pdfkit/.eslintrc.js
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'no-bitwise': 0,
'no-plusplus': 0,
'vars-on-top': 0,
'no-continue': 0,
'prefer-const': 0,
'default-case': 0,
'dot-notation': 1,
Expand All @@ -20,7 +21,7 @@ module.exports = {
'no-path-concat': 0,
'import/no-cycle': 0,
'no-multi-assign': 0,
'no-new-wrappers': 1,
'no-new-wrappers': 0,
'prefer-template': 0,
'no-throw-literal': 0,
'no-return-assign': 0,
Expand All @@ -30,6 +31,7 @@ module.exports = {
'no-param-reassign': 0,
'prefer-rest-params': 0,
'prefer-object-spread': 0,
'prefer-destructuring': 0,
'max-classes-per-file': 0,
'no-restricted-syntax': 0,
'no-use-before-define': 1,
Expand Down
25 changes: 9 additions & 16 deletions packages/pdfkit/src/data.js
@@ -1,5 +1,3 @@
import range from './utils/range';

class Data {
constructor(data = []) {
this.pos = 0;
Expand Down Expand Up @@ -87,21 +85,20 @@ class Data {

readString(length) {
const ret = [];
for (
let i = 0, end = length, asc = 0 <= end;
asc ? i < end : i > end;
asc ? i++ : i--
) {
for (let i = 0; i < length; i++) {
ret[i] = String.fromCharCode(this.readByte());
}

return ret.join('');
}

writeString(val) {
return range(0, val.length, false).map(i =>
this.writeByte(val.charCodeAt(i)),
);
// todo: remove returning data. Seems not used
const result = [];
for (let i = 0; i <= val.length; i++) {
result.push(this.writeByte(val.charCodeAt(i)));
}
return result;
}

stringAt(pos, length) {
Expand Down Expand Up @@ -182,19 +179,15 @@ class Data {

read(bytes) {
const buf = [];
for (
let i = 0, end = bytes, asc = 0 <= end;
asc ? i < end : i > end;
asc ? i++ : i--
) {
for (let i = 0; i < bytes; i++) {
buf.push(this.readByte());
}

return buf;
}

write(bytes) {
return Array.from(bytes).map(byte => this.writeByte(byte));
return bytes.map(byte => this.writeByte(byte));
}
}

Expand Down
78 changes: 47 additions & 31 deletions packages/pdfkit/src/document.js
@@ -1,17 +1,18 @@
import stream from 'stream';
import PDFObject from './object';
import PDFReference from './reference';
import PDFNameTree from './name_tree';
import PDFPage from './page';
import Color from './mixins/color';
import Vector from './mixins/vector';
import Fonts from './mixins/fonts';
import Text from './mixins/text';
import Images from './mixins/images';
import Annotations from './mixins/annotations';
import PDFNameTree from './name_tree';
import PDFSecurity from './security';
import ColorMixin from './mixins/color';
import VectorMixin from './mixins/vector';
import FontsMixin from './mixins/fonts';
import TextMixin from './mixins/text';
import ImagesMixin from './mixins/images';
import AnnotationsMixin from './mixins/annotations';
import OutlineMixin from './mixins/outline';
import AcroFormMixin from './mixins/acroform';
import Attachments from './mixins/attachments';
import AttachmentsMixin from './mixins/attachments';
import capitalize from './utils/capitalize';

class PDFDocument extends stream.Readable {
Expand Down Expand Up @@ -90,6 +91,7 @@ class PDFDocument extends stream.Readable {
this.initText();
this.initImages();
this.initOutline();
// this.initMarkings(options)

// Initialize the metadata
this.info = {
Expand All @@ -111,6 +113,12 @@ class PDFDocument extends stream.Readable {
});
}

// Generate file ID
this._id = PDFSecurity.generateFileID(this.info);

// Initialize security settings
// this._security = PDFSecurity.create(this, options);

// Write the header PDF version
this._write(`%PDF-${this.version}`);

Expand All @@ -129,6 +137,7 @@ class PDFDocument extends stream.Readable {
({ options } = this);
}

// end the current page if needed
if (!this.options.bufferPages) {
this.flushPages();
}
Expand All @@ -147,6 +156,8 @@ class PDFDocument extends stream.Readable {
this._ctm = [1, 0, 0, 1, 0, 0];
this.transform(1, 0, 0, -1, 0, this.page.height);

// this.emit('pageAdded');

return this;
}

Expand All @@ -157,6 +168,7 @@ class PDFDocument extends stream.Readable {
this._pageBuffer = [];
this._pageBufferStart += pages.length;
for (let page of Array.from(pages)) {
// this.endPageMarkings(page);
page.end();
}
}
Expand Down Expand Up @@ -251,6 +263,7 @@ class PDFDocument extends stream.Readable {
}

this.endOutline();
// this.endMarkings();

this._root.end();
this._root.data.Pages.end();
Expand All @@ -261,14 +274,18 @@ class PDFDocument extends stream.Readable {
this._root.data.ViewerPreferences.end();
}

// if (this._security) {
// this._security.end();
// }

if (this._waiting === 0) {
return this._finalize();
}

this._ended = true;
}

_finalize(fn) {
_finalize() {
// generate xref
const xRefOffset = this._offset;
this._write('xref');
Expand All @@ -281,14 +298,19 @@ class PDFDocument extends stream.Readable {
}

// trailer
const trailer = {
Size: this._offsets.length + 1,
Root: this._root,
Info: this._info,
ID: [this._id, this._id]
};

// if (this._security) {
// trailer.Encrypt = this._security.dictionary;
// }

this._write('trailer');
this._write(
PDFObject.convert({
Size: this._offsets.length + 1,
Root: this._root,
Info: this._info
})
);
this._write(PDFObject.convert(trailer));

this._write('startxref');
this._write(`${xRefOffset}`);
Expand All @@ -304,25 +326,19 @@ class PDFDocument extends stream.Readable {
}

const mixin = methods => {
return (() => {
const result = [];
for (let name in methods) {
const method = methods[name];
result.push((PDFDocument.prototype[name] = method));
}
return result;
})();
Object.assign(PDFDocument.prototype, methods);
};

// Load mixins
mixin(Color);
mixin(Vector);
mixin(Fonts);
mixin(Text);
mixin(Images);
mixin(Annotations);
mixin(ColorMixin);
mixin(VectorMixin);
mixin(FontsMixin);
mixin(TextMixin);
mixin(ImagesMixin);
mixin(AnnotationsMixin);
mixin(OutlineMixin);
// mixin(MarkingsMixin);
mixin(AcroFormMixin);
mixin(Attachments);
mixin(AttachmentsMixin);

export default PDFDocument;
4 changes: 2 additions & 2 deletions packages/pdfkit/src/font.js
Expand Up @@ -28,11 +28,11 @@ export class PDFFont {
return new EmbeddedFont(document, font, id);
}

encode(text) {
encode() {
throw new Error('Must be implemented by subclasses');
}

widthOfString(text) {
widthOfString() {
throw new Error('Must be implemented by subclasses');
}

Expand Down
36 changes: 20 additions & 16 deletions packages/pdfkit/src/mixins/acroform.js
Expand Up @@ -11,33 +11,33 @@ const FIELD_FLAGS = {
edit: 0x40000,
sort: 0x80000,
multiSelect: 0x200000,
noSpell: 0x400000,
noSpell: 0x400000
};
const FIELD_JUSTIFY = {
left: 0,
center: 1,
right: 2,
right: 2
};
const VALUE_MAP = { value: 'V', defaultValue: 'DV' };
const FORMAT_SPECIAL = {
zip: '0',
zipPlus4: '1',
zip4: '1',
phone: '2',
ssn: '3',
ssn: '3'
};
const FORMAT_DEFAULT = {
number: {
nDec: 0,
sepComma: false,
negStyle: 'MinusBlack',
currency: '',
currencyPrepend: true,
currencyPrepend: true
},
percent: {
nDec: 0,
sepComma: false,
},
sepComma: false
}
};

export default {
Expand All @@ -51,7 +51,7 @@ export default {
}
this._acroform = {
fonts: {},
defaultFont: this._font.name,
defaultFont: this._font.name
};
this._acroform.fonts[this._font.id] = this._font.ref();

Expand All @@ -60,8 +60,8 @@ export default {
NeedAppearances: true,
DA: new String(`/${this._font.id} 0 Tf 0 g`),
DR: {
Font: {},
},
Font: {}
}
};
data.DR.Font[this._font.id] = this._font.ref();
const AcroForm = this.ref(data);
Expand Down Expand Up @@ -181,7 +181,7 @@ export default {
_fieldDict(name, type, options = {}) {
if (!this._acroform) {
throw new Error(
'Call document.initForms() method before adding form elements to document',
'Call document.initForms() method before adding form elements to document'
);
}
let opts = Object.assign({}, options);
Expand Down Expand Up @@ -253,8 +253,8 @@ export default {
'"' + p.negStyle + '"',
'null',
'"' + p.currency + '"',
String(p.currencyPrepend),
].join(','),
String(p.currencyPrepend)
].join(',')
);
} else if (f.type === 'percent') {
let p = Object.assign({}, FORMAT_DEFAULT.percent, f);
Expand All @@ -264,11 +264,11 @@ export default {
opts.AA = opts.AA ? opts.AA : {};
opts.AA.K = {
S: 'JavaScript',
JS: new String(`${fnKeystroke}(${params});`),
JS: new String(`${fnKeystroke}(${params});`)
};
opts.AA.F = {
S: 'JavaScript',
JS: new String(`${fnFormat}(${params});`),
JS: new String(`${fnFormat}(${params});`)
};
}
delete opts.format;
Expand Down Expand Up @@ -333,8 +333,12 @@ export default {
// add current font to field's resource dict (RD) if not the default acroform font
if (this._acroform.defaultFont !== this._font.name) {
options.DR = { Font: {} };

// Get the fontSize option. If not set use auto sizing
const fontSize = options.fontSize || 0;

options.DR.Font[this._font.id] = this._font.ref();
options.DA = new String(`/${this._font.id} 0 Tf 0 g`);
options.DA = new String(`/${this._font.id} ${fontSize} Tf 0 g`);
}
return options;
},
Expand Down Expand Up @@ -382,5 +386,5 @@ export default {
delete options.label;
}
return options;
},
}
};

0 comments on commit 9527fe4

Please sign in to comment.