pdfmake 0.3.0-beta.1 → 0.3.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
Binary file
package/js/DocMeasure.js CHANGED
@@ -70,6 +70,8 @@ class DocMeasure {
70
70
  return extendMargins(this.measureCanvas(node));
71
71
  } else if (node.qr) {
72
72
  return extendMargins(this.measureQr(node));
73
+ } else if (node.attachment) {
74
+ return extendMargins(this.measureAttachment(node));
73
75
  } else {
74
76
  throw new Error(`Unrecognized document structure: ${(0, _node.stringifyNode)(node)}`);
75
77
  }
@@ -744,6 +746,12 @@ class DocMeasure {
744
746
  return node;
745
747
  }
746
748
 
749
+ measureAttachment(node) {
750
+ node._width = node.width || 7;
751
+ node._height = node.height || 18;
752
+ return node;
753
+ }
754
+
747
755
  }
748
756
 
749
757
  var _default = DocMeasure;
@@ -66,6 +66,8 @@ class DocPreprocessor {
66
66
  return this.preprocessCanvas(node);
67
67
  } else if (node.qr) {
68
68
  return this.preprocessQr(node);
69
+ } else if (node.attachment) {
70
+ return this.preprocessAttachment(node);
69
71
  } else if (node.pageReference || node.textReference) {
70
72
  return this.preprocessText(node);
71
73
  } else {
@@ -271,6 +273,10 @@ class DocPreprocessor {
271
273
  return node;
272
274
  }
273
275
 
276
+ preprocessAttachment(node) {
277
+ return node;
278
+ }
279
+
274
280
  _getNodeForNodeRef(node) {
275
281
  if (this.parentNode) {
276
282
  return this.parentNode;
@@ -187,6 +187,29 @@ class ElementWriter extends _events.EventEmitter {
187
187
  return position;
188
188
  }
189
189
 
190
+ addAttachment(attachment, index) {
191
+ let context = this.context();
192
+ let page = context.getCurrentPage();
193
+ let position = this.getCurrentPositionOnPage();
194
+
195
+ if (!page || attachment.absolutePosition === undefined && context.availableHeight < attachment._height && page.items.length > 0) {
196
+ return false;
197
+ }
198
+
199
+ if (attachment._x === undefined) {
200
+ attachment._x = attachment.x || 0;
201
+ }
202
+
203
+ attachment.x = context.x + attachment._x;
204
+ attachment.y = context.y;
205
+ addPageItem(page, {
206
+ type: 'attachment',
207
+ item: attachment
208
+ }, index);
209
+ context.moveDown(attachment._height);
210
+ return position;
211
+ }
212
+
190
213
  alignImage(image) {
191
214
  let width = this.context().availableWidth;
192
215
  let imageWidth = image._minWidth;
@@ -454,6 +454,8 @@ class LayoutBuilder {
454
454
  this.processCanvas(node);
455
455
  } else if (node.qr) {
456
456
  this.processQr(node);
457
+ } else if (node.attachment) {
458
+ this.processAttachment(node);
457
459
  } else if (!node._span) {
458
460
  throw new Error(`Unrecognized document structure: ${(0, _node.stringifyNode)(node)}`);
459
461
  }
@@ -790,6 +792,11 @@ class LayoutBuilder {
790
792
  node.positions.push(position);
791
793
  }
792
794
 
795
+ processAttachment(node) {
796
+ let position = this.writer.addAttachment(node);
797
+ node.positions.push(position);
798
+ }
799
+
793
800
  }
794
801
 
795
802
  function decorateNode(node) {
package/js/PDFDocument.js CHANGED
@@ -22,7 +22,7 @@ const typeName = (bold, italics) => {
22
22
  };
23
23
 
24
24
  class PDFDocument extends _pdfkit.default {
25
- constructor(fonts = {}, images = {}, patterns = {}, options = {}, virtualfs = null) {
25
+ constructor(fonts = {}, images = {}, patterns = {}, attachments = {}, options = {}, virtualfs = null) {
26
26
  super(options);
27
27
  this.fonts = {};
28
28
  this.fontCache = {};
@@ -49,6 +49,7 @@ class PDFDocument extends _pdfkit.default {
49
49
  }
50
50
 
51
51
  this.images = images;
52
+ this.attachments = attachments;
52
53
  this.virtualfs = virtualfs;
53
54
  }
54
55
 
@@ -147,6 +148,32 @@ class PDFDocument extends _pdfkit.default {
147
148
  return null;
148
149
  }
149
150
 
151
+ provideAttachment(src) {
152
+ const checkRequired = obj => {
153
+ if (!obj) {
154
+ throw new Error('No attachment');
155
+ }
156
+
157
+ if (!obj.src) {
158
+ throw new Error('The "src" key is required for attachments');
159
+ }
160
+
161
+ return obj;
162
+ };
163
+
164
+ if (typeof src === 'object') {
165
+ return checkRequired(src);
166
+ }
167
+
168
+ let attachment = checkRequired(this.attachments[src]);
169
+
170
+ if (this.virtualfs && this.virtualfs.existsSync(attachment.src)) {
171
+ return this.virtualfs.readFileSync(attachment.src);
172
+ }
173
+
174
+ return attachment;
175
+ }
176
+
150
177
  setOpenActionAsPrint() {
151
178
  let printActionRef = this.ref({
152
179
  Type: 'Action',
@@ -42,6 +42,10 @@ class PageElementWriter extends _ElementWriter.default {
42
42
  return this._fitOnPage(() => super.addQr(qr, index));
43
43
  }
44
44
 
45
+ addAttachment(attachment, index) {
46
+ return this._fitOnPage(() => super.addAttachment(attachment, index));
47
+ }
48
+
45
49
  addVector(vector, ignoreContextX, ignoreContextY, index) {
46
50
  return super.addVector(vector, ignoreContextX, ignoreContextY, index);
47
51
  }
package/js/Printer.js CHANGED
@@ -62,6 +62,7 @@ class PdfPrinter {
62
62
  docDefinition.version = docDefinition.version || '1.3';
63
63
  docDefinition.compress = typeof docDefinition.compress === 'boolean' ? docDefinition.compress : true;
64
64
  docDefinition.images = docDefinition.images || {};
65
+ docDefinition.attachments = docDefinition.attachments || {};
65
66
  docDefinition.pageMargins = (0, _variableType.isValue)(docDefinition.pageMargins) ? docDefinition.pageMargins : 40;
66
67
  docDefinition.patterns = docDefinition.patterns || {};
67
68
  let pageSize = (0, _PageSize.normalizePageSize)(docDefinition.pageSize, docDefinition.pageOrientation);
@@ -78,7 +79,8 @@ class PdfPrinter {
78
79
  info: createMetadata(docDefinition),
79
80
  font: null
80
81
  };
81
- this.pdfKitDoc = new _PDFDocument.default(this.fontDescriptors, docDefinition.images, docDefinition.patterns, pdfOptions, this.virtualfs);
82
+ this.pdfKitDoc = new _PDFDocument.default(this.fontDescriptors, docDefinition.images, docDefinition.patterns, docDefinition.attachments, pdfOptions, this.virtualfs);
83
+ embedFiles(docDefinition, this.pdfKitDoc);
82
84
  const builder = new _LayoutBuilder.default(pageSize, (0, _PageSize.normalizePageMargin)(docDefinition.pageMargins), new _SVGMeasure.default());
83
85
  builder.registerTableLayouts(_tableLayouts.tableLayouts);
84
86
 
@@ -121,6 +123,20 @@ class PdfPrinter {
121
123
 
122
124
 
123
125
  resolveUrls(docDefinition) {
126
+ const getExtendedUrl = url => {
127
+ if (typeof url === 'object') {
128
+ return {
129
+ url: url.url,
130
+ headers: url.headers
131
+ };
132
+ }
133
+
134
+ return {
135
+ url: url,
136
+ headers: {}
137
+ };
138
+ };
139
+
124
140
  return new Promise((resolve, reject) => {
125
141
  if (this.urlResolver === null) {
126
142
  resolve();
@@ -129,19 +145,55 @@ class PdfPrinter {
129
145
  for (let font in this.fontDescriptors) {
130
146
  if (this.fontDescriptors.hasOwnProperty(font)) {
131
147
  if (this.fontDescriptors[font].normal) {
132
- this.urlResolver.resolve(this.fontDescriptors[font].normal);
148
+ if (Array.isArray(this.fontDescriptors[font].normal)) {
149
+ // TrueType Collection
150
+ let url = getExtendedUrl(this.fontDescriptors[font].normal[0]);
151
+ this.urlResolver.resolve(url.url, url.headers);
152
+ this.fontDescriptors[font].normal[0] = url.url;
153
+ } else {
154
+ let url = getExtendedUrl(this.fontDescriptors[font].normal);
155
+ this.urlResolver.resolve(url.url, url.headers);
156
+ this.fontDescriptors[font].normal = url.url;
157
+ }
133
158
  }
134
159
 
135
160
  if (this.fontDescriptors[font].bold) {
136
- this.urlResolver.resolve(this.fontDescriptors[font].bold);
161
+ if (Array.isArray(this.fontDescriptors[font].bold)) {
162
+ // TrueType Collection
163
+ let url = getExtendedUrl(this.fontDescriptors[font].bold[0]);
164
+ this.urlResolver.resolve(url.url, url.headers);
165
+ this.fontDescriptors[font].bold[0] = url.url;
166
+ } else {
167
+ let url = getExtendedUrl(this.fontDescriptors[font].bold);
168
+ this.urlResolver.resolve(url.url, url.headers);
169
+ this.fontDescriptors[font].bold = url.url;
170
+ }
137
171
  }
138
172
 
139
173
  if (this.fontDescriptors[font].italics) {
140
- this.urlResolver.resolve(this.fontDescriptors[font].italics);
174
+ if (Array.isArray(this.fontDescriptors[font].italics)) {
175
+ // TrueType Collection
176
+ let url = getExtendedUrl(this.fontDescriptors[font].italics[0]);
177
+ this.urlResolver.resolve(url.url, url.headers);
178
+ this.fontDescriptors[font].italics[0] = url.url;
179
+ } else {
180
+ let url = getExtendedUrl(this.fontDescriptors[font].italics);
181
+ this.urlResolver.resolve(url.url, url.headers);
182
+ this.fontDescriptors[font].italics = url.url;
183
+ }
141
184
  }
142
185
 
143
186
  if (this.fontDescriptors[font].bolditalics) {
144
- this.urlResolver.resolve(this.fontDescriptors[font].bolditalics);
187
+ if (Array.isArray(this.fontDescriptors[font].bolditalics)) {
188
+ // TrueType Collection
189
+ let url = getExtendedUrl(this.fontDescriptors[font].bolditalics[0]);
190
+ this.urlResolver.resolve(url.url, url.headers);
191
+ this.fontDescriptors[font].bolditalics[0] = url.url;
192
+ } else {
193
+ let url = getExtendedUrl(this.fontDescriptors[font].bolditalics);
194
+ this.urlResolver.resolve(url.url, url.headers);
195
+ this.fontDescriptors[font].bolditalics = url.url;
196
+ }
145
197
  }
146
198
  }
147
199
  }
@@ -149,7 +201,29 @@ class PdfPrinter {
149
201
  if (docDefinition.images) {
150
202
  for (let image in docDefinition.images) {
151
203
  if (docDefinition.images.hasOwnProperty(image)) {
152
- this.urlResolver.resolve(docDefinition.images[image]);
204
+ let url = getExtendedUrl(docDefinition.images[image]);
205
+ this.urlResolver.resolve(url.url, url.headers);
206
+ docDefinition.images[image] = url.url;
207
+ }
208
+ }
209
+ }
210
+
211
+ if (docDefinition.attachments) {
212
+ for (let attachment in docDefinition.attachments) {
213
+ if (docDefinition.attachments.hasOwnProperty(attachment) && docDefinition.attachments[attachment].src) {
214
+ let url = getExtendedUrl(docDefinition.attachments[attachment].src);
215
+ this.urlResolver.resolve(url.url, url.headers);
216
+ docDefinition.attachments[attachment].src = url.url;
217
+ }
218
+ }
219
+ }
220
+
221
+ if (docDefinition.files) {
222
+ for (let file in docDefinition.files) {
223
+ if (docDefinition.files.hasOwnProperty(file) && docDefinition.files[file].src) {
224
+ let url = getExtendedUrl(docDefinition.files[file].src);
225
+ this.urlResolver.resolve(url.url, url.headers);
226
+ docDefinition.files[file].src = url.url;
153
227
  }
154
228
  }
155
229
  }
@@ -199,6 +273,22 @@ function createMetadata(docDefinition) {
199
273
  return info;
200
274
  }
201
275
 
276
+ function embedFiles(docDefinition, pdfKitDoc) {
277
+ if (docDefinition.files) {
278
+ for (const key in docDefinition.files) {
279
+ const file = docDefinition.files[key];
280
+ if (!file.src) return;
281
+
282
+ if (pdfKitDoc.virtualfs && pdfKitDoc.virtualfs.existsSync(file.src)) {
283
+ file.src = pdfKitDoc.virtualfs.readFileSync(file.src);
284
+ }
285
+
286
+ file.name = file.name || key;
287
+ pdfKitDoc.file(file.src, file);
288
+ }
289
+ }
290
+ }
291
+
202
292
  function calculatePageHeight(pages, margins) {
203
293
  function getItemHeight(item) {
204
294
  if (typeof item.item.getHeight === 'function') {
@@ -206,7 +296,11 @@ function calculatePageHeight(pages, margins) {
206
296
  } else if (item.item._height) {
207
297
  return item.item._height;
208
298
  } else if (item.type === 'vector') {
209
- return item.item.y1 > item.item.y2 ? item.item.y1 : item.item.y2;
299
+ if (typeof item.item.y1 !== 'undefined') {
300
+ return item.item.y1 > item.item.y2 ? item.item.y1 : item.item.y2;
301
+ } else {
302
+ return item.item.h;
303
+ }
210
304
  } else {
211
305
  // TODO: add support for next item types
212
306
  return 0;
package/js/Renderer.js CHANGED
@@ -100,6 +100,10 @@ class Renderer {
100
100
  this.renderSVG(item.item);
101
101
  break;
102
102
 
103
+ case 'attachment':
104
+ this.renderAttachment(item.item);
105
+ break;
106
+
103
107
  case 'beginClip':
104
108
  this.beginClip(item.item);
105
109
  break;
@@ -364,6 +368,21 @@ class Renderer {
364
368
  if (image.linkToDestination) {
365
369
  this.pdfDocument.goTo(image.x, image.y, image._width, image._height, image.linkToDestination);
366
370
  }
371
+
372
+ if (image.linkToFile) {
373
+ const attachment = this.pdfDocument.provideAttachment(image.linkToFile);
374
+ this.pdfDocument.fileAnnotation(image.x, image.y, image._width, image._height, attachment, // add empty rectangle as file annotation appearance with the same size as the rendered image
375
+ {
376
+ AP: {
377
+ N: {
378
+ Type: 'XObject',
379
+ Subtype: 'Form',
380
+ FormType: 1,
381
+ BBox: [image.x, image.y, image._width, image._height]
382
+ }
383
+ }
384
+ });
385
+ }
367
386
  }
368
387
 
369
388
  renderSVG(svg) {
@@ -389,6 +408,17 @@ class Renderer {
389
408
  (0, _svgToPdfkit.default)(this.pdfDocument, svg.svg, svg.x, svg.y, options);
390
409
  }
391
410
 
411
+ renderAttachment(attachment) {
412
+ const file = this.pdfDocument.provideAttachment(attachment.attachment);
413
+ const options = {};
414
+
415
+ if (attachment.icon) {
416
+ options.Name = attachment.icon;
417
+ }
418
+
419
+ this.pdfDocument.fileAnnotation(attachment.x, attachment.y, attachment._width, attachment._height, file, options);
420
+ }
421
+
392
422
  beginClip(rect) {
393
423
  this.pdfDocument.save();
394
424
  this.pdfDocument.addContent(`${rect.x} ${rect.y} ${rect.width} ${rect.height} re`);
package/js/URLResolver.js CHANGED
@@ -9,11 +9,14 @@ var _https = _interopRequireDefault(require("https"));
9
9
 
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
11
 
12
- const fetchUrl = url => {
12
+ const fetchUrl = (url, headers = {}) => {
13
13
  return new Promise((resolve, reject) => {
14
14
  const parsedUrl = new URL(url);
15
15
  const h = parsedUrl.protocol === 'https:' ? _https.default : _http.default;
16
- h.get(url, res => {
16
+ let options = {
17
+ headers: headers
18
+ };
19
+ h.get(url, options, res => {
17
20
  if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
18
21
  // redirect url
19
22
  fetchUrl(res.headers.location).then(buffer => {
@@ -43,16 +46,21 @@ class URLResolver {
43
46
  this.resolving = {};
44
47
  }
45
48
 
46
- resolve(url) {
49
+ resolve(url, headers = {}) {
47
50
  if (!this.resolving[url]) {
48
51
  this.resolving[url] = new Promise((resolve, reject) => {
49
52
  if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
50
- fetchUrl(url).then(buffer => {
51
- this.fs.writeFileSync(url, buffer);
53
+ if (this.fs.existsSync(url)) {
54
+ // url was downloaded earlier
52
55
  resolve();
53
- }, result => {
54
- reject(result);
55
- });
56
+ } else {
57
+ fetchUrl(url, headers).then(buffer => {
58
+ this.fs.writeFileSync(url, buffer);
59
+ resolve();
60
+ }, result => {
61
+ reject(result);
62
+ });
63
+ }
56
64
  } else {
57
65
  // cannot be resolved
58
66
  resolve();
@@ -3,10 +3,15 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
 
6
- const fetchUrl = url => {
6
+ const fetchUrl = (url, headers = {}) => {
7
7
  return new Promise((resolve, reject) => {
8
8
  const xhr = new XMLHttpRequest();
9
9
  xhr.open('GET', url, true);
10
+
11
+ for (let headerName in headers) {
12
+ xhr.setRequestHeader(headerName, headers[headerName]);
13
+ }
14
+
10
15
  xhr.responseType = 'arraybuffer';
11
16
 
12
17
  xhr.onreadystatechange = () => {
@@ -53,11 +58,11 @@ class URLBrowserResolver {
53
58
  this.resolving = {};
54
59
  }
55
60
 
56
- resolve(url) {
61
+ resolve(url, headers = {}) {
57
62
  if (!this.resolving[url]) {
58
63
  this.resolving[url] = new Promise((resolve, reject) => {
59
64
  if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
60
- fetchUrl(url).then(buffer => {
65
+ fetchUrl(url, headers).then(buffer => {
61
66
  this.fs.writeFileSync(url, buffer);
62
67
  resolve();
63
68
  }, result => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdfmake",
3
- "version": "0.3.0-beta.1",
3
+ "version": "0.3.0-beta.3",
4
4
  "description": "Client/server side PDF printing in pure JavaScript",
5
5
  "main": "js/index.js",
6
6
  "esnext": "src/index.js",
package/src/DocMeasure.js CHANGED
@@ -61,6 +61,8 @@ class DocMeasure {
61
61
  return extendMargins(this.measureCanvas(node));
62
62
  } else if (node.qr) {
63
63
  return extendMargins(this.measureQr(node));
64
+ } else if (node.attachment) {
65
+ return extendMargins(this.measureAttachment(node));
64
66
  } else {
65
67
  throw new Error(`Unrecognized document structure: ${stringifyNode(node)}`);
66
68
  }
@@ -689,6 +691,13 @@ class DocMeasure {
689
691
  node._alignment = this.styleStack.getProperty('alignment');
690
692
  return node;
691
693
  }
694
+
695
+ measureAttachment(node) {
696
+ node._width = node.width || 7;
697
+ node._height = node.height || 18;
698
+
699
+ return node;
700
+ }
692
701
  }
693
702
 
694
703
  export default DocMeasure;
@@ -55,6 +55,8 @@ class DocPreprocessor {
55
55
  return this.preprocessCanvas(node);
56
56
  } else if (node.qr) {
57
57
  return this.preprocessQr(node);
58
+ } else if (node.attachment) {
59
+ return this.preprocessAttachment(node);
58
60
  } else if (node.pageReference || node.textReference) {
59
61
  return this.preprocessText(node);
60
62
  } else {
@@ -246,6 +248,10 @@ class DocPreprocessor {
246
248
  return node;
247
249
  }
248
250
 
251
+ preprocessAttachment(node) {
252
+ return node;
253
+ }
254
+
249
255
  _getNodeForNodeRef(node) {
250
256
  if (this.parentNode) {
251
257
  return this.parentNode;
@@ -196,6 +196,32 @@ class ElementWriter extends EventEmitter {
196
196
  return position;
197
197
  }
198
198
 
199
+ addAttachment(attachment, index) {
200
+ let context = this.context();
201
+ let page = context.getCurrentPage();
202
+ let position = this.getCurrentPositionOnPage();
203
+
204
+ if (!page || (attachment.absolutePosition === undefined && context.availableHeight < attachment._height && page.items.length > 0)) {
205
+ return false;
206
+ }
207
+
208
+ if (attachment._x === undefined) {
209
+ attachment._x = attachment.x || 0;
210
+ }
211
+
212
+ attachment.x = context.x + attachment._x;
213
+ attachment.y = context.y;
214
+
215
+ addPageItem(page, {
216
+ type: 'attachment',
217
+ item: attachment
218
+ }, index);
219
+
220
+ context.moveDown(attachment._height);
221
+
222
+ return position;
223
+ }
224
+
199
225
  alignImage(image) {
200
226
  let width = this.context().availableWidth;
201
227
  let imageWidth = image._minWidth;
@@ -439,6 +439,8 @@ class LayoutBuilder {
439
439
  this.processCanvas(node);
440
440
  } else if (node.qr) {
441
441
  this.processQr(node);
442
+ } else if (node.attachment) {
443
+ this.processAttachment(node);
442
444
  } else if (!node._span) {
443
445
  throw new Error(`Unrecognized document structure: ${stringifyNode(node)}`);
444
446
  }
@@ -774,6 +776,11 @@ class LayoutBuilder {
774
776
  let position = this.writer.addQr(node);
775
777
  node.positions.push(position);
776
778
  }
779
+
780
+ processAttachment(node) {
781
+ let position = this.writer.addAttachment(node);
782
+ node.positions.push(position);
783
+ }
777
784
  }
778
785
 
779
786
  function decorateNode(node) {
@@ -13,7 +13,7 @@ const typeName = (bold, italics) => {
13
13
  };
14
14
 
15
15
  class PDFDocument extends PDFKit {
16
- constructor(fonts = {}, images = {}, patterns = {}, options = {}, virtualfs = null) {
16
+ constructor(fonts = {}, images = {}, patterns = {}, attachments = {}, options = {}, virtualfs = null) {
17
17
  super(options);
18
18
 
19
19
  this.fonts = {};
@@ -41,6 +41,7 @@ class PDFDocument extends PDFKit {
41
41
 
42
42
 
43
43
  this.images = images;
44
+ this.attachments = attachments;
44
45
  this.virtualfs = virtualfs;
45
46
  }
46
47
 
@@ -134,6 +135,31 @@ class PDFDocument extends PDFKit {
134
135
  return null;
135
136
  }
136
137
 
138
+ provideAttachment(src) {
139
+ const checkRequired = obj => {
140
+ if (!obj) {
141
+ throw new Error('No attachment');
142
+ }
143
+ if (!obj.src) {
144
+ throw new Error('The "src" key is required for attachments');
145
+ }
146
+
147
+ return obj;
148
+ };
149
+
150
+ if (typeof src === 'object') {
151
+ return checkRequired(src);
152
+ }
153
+
154
+ let attachment = checkRequired(this.attachments[src]);
155
+
156
+ if (this.virtualfs && this.virtualfs.existsSync(attachment.src)) {
157
+ return this.virtualfs.readFileSync(attachment.src);
158
+ }
159
+
160
+ return attachment;
161
+ }
162
+
137
163
  setOpenActionAsPrint() {
138
164
  let printActionRef = this.ref({
139
165
  Type: 'Action',
@@ -35,6 +35,10 @@ class PageElementWriter extends ElementWriter {
35
35
  return this._fitOnPage(() => super.addQr(qr, index));
36
36
  }
37
37
 
38
+ addAttachment(attachment, index) {
39
+ return this._fitOnPage(() => super.addAttachment(attachment, index));
40
+ }
41
+
38
42
  addVector(vector, ignoreContextX, ignoreContextY, index) {
39
43
  return super.addVector(vector, ignoreContextX, ignoreContextY, index);
40
44
  }