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.
package/src/Printer.js CHANGED
@@ -49,6 +49,7 @@ class PdfPrinter {
49
49
  docDefinition.version = docDefinition.version || '1.3';
50
50
  docDefinition.compress = typeof docDefinition.compress === 'boolean' ? docDefinition.compress : true;
51
51
  docDefinition.images = docDefinition.images || {};
52
+ docDefinition.attachments = docDefinition.attachments || {};
52
53
  docDefinition.pageMargins = isValue(docDefinition.pageMargins) ? docDefinition.pageMargins : 40;
53
54
  docDefinition.patterns = docDefinition.patterns || {};
54
55
 
@@ -68,7 +69,8 @@ class PdfPrinter {
68
69
  font: null
69
70
  };
70
71
 
71
- this.pdfKitDoc = new PDFDocument(this.fontDescriptors, docDefinition.images, docDefinition.patterns, pdfOptions, this.virtualfs);
72
+ this.pdfKitDoc = new PDFDocument(this.fontDescriptors, docDefinition.images, docDefinition.patterns, docDefinition.attachments, pdfOptions, this.virtualfs);
73
+ embedFiles(docDefinition, this.pdfKitDoc);
72
74
 
73
75
  const builder = new LayoutBuilder(pageSize, normalizePageMargin(docDefinition.pageMargins), new SVGMeasure());
74
76
 
@@ -108,6 +110,14 @@ class PdfPrinter {
108
110
  * @returns {Promise}
109
111
  */
110
112
  resolveUrls(docDefinition) {
113
+ const getExtendedUrl = url => {
114
+ if (typeof url === 'object') {
115
+ return { url: url.url, headers: url.headers };
116
+ }
117
+
118
+ return { url: url, headers: {} };
119
+ };
120
+
111
121
  return new Promise((resolve, reject) => {
112
122
  if (this.urlResolver === null) {
113
123
  resolve();
@@ -116,16 +126,48 @@ class PdfPrinter {
116
126
  for (let font in this.fontDescriptors) {
117
127
  if (this.fontDescriptors.hasOwnProperty(font)) {
118
128
  if (this.fontDescriptors[font].normal) {
119
- this.urlResolver.resolve(this.fontDescriptors[font].normal);
129
+ if (Array.isArray(this.fontDescriptors[font].normal)) { // TrueType Collection
130
+ let url = getExtendedUrl(this.fontDescriptors[font].normal[0]);
131
+ this.urlResolver.resolve(url.url, url.headers);
132
+ this.fontDescriptors[font].normal[0] = url.url;
133
+ } else {
134
+ let url = getExtendedUrl(this.fontDescriptors[font].normal);
135
+ this.urlResolver.resolve(url.url, url.headers);
136
+ this.fontDescriptors[font].normal = url.url;
137
+ }
120
138
  }
121
139
  if (this.fontDescriptors[font].bold) {
122
- this.urlResolver.resolve(this.fontDescriptors[font].bold);
140
+ if (Array.isArray(this.fontDescriptors[font].bold)) { // TrueType Collection
141
+ let url = getExtendedUrl(this.fontDescriptors[font].bold[0]);
142
+ this.urlResolver.resolve(url.url, url.headers);
143
+ this.fontDescriptors[font].bold[0] = url.url;
144
+ } else {
145
+ let url = getExtendedUrl(this.fontDescriptors[font].bold);
146
+ this.urlResolver.resolve(url.url, url.headers);
147
+ this.fontDescriptors[font].bold = url.url;
148
+ }
123
149
  }
124
150
  if (this.fontDescriptors[font].italics) {
125
- this.urlResolver.resolve(this.fontDescriptors[font].italics);
151
+ if (Array.isArray(this.fontDescriptors[font].italics)) { // TrueType Collection
152
+ let url = getExtendedUrl(this.fontDescriptors[font].italics[0]);
153
+ this.urlResolver.resolve(url.url, url.headers);
154
+ this.fontDescriptors[font].italics[0] = url.url;
155
+ } else {
156
+ let url = getExtendedUrl(this.fontDescriptors[font].italics);
157
+ this.urlResolver.resolve(url.url, url.headers);
158
+ this.fontDescriptors[font].italics = url.url;
159
+ }
126
160
  }
127
161
  if (this.fontDescriptors[font].bolditalics) {
128
- this.urlResolver.resolve(this.fontDescriptors[font].bolditalics);
162
+ if (Array.isArray(this.fontDescriptors[font].bolditalics)) { // TrueType Collection
163
+ let url = getExtendedUrl(this.fontDescriptors[font].bolditalics[0]);
164
+ this.urlResolver.resolve(url.url, url.headers);
165
+ this.fontDescriptors[font].bolditalics[0] = url.url;
166
+ } else {
167
+ let url = getExtendedUrl(this.fontDescriptors[font].bolditalics);
168
+ this.urlResolver.resolve(url.url, url.headers);
169
+ this.fontDescriptors[font].bolditalics = url.url;
170
+ }
129
171
  }
130
172
  }
131
173
  }
@@ -133,7 +175,29 @@ class PdfPrinter {
133
175
  if (docDefinition.images) {
134
176
  for (let image in docDefinition.images) {
135
177
  if (docDefinition.images.hasOwnProperty(image)) {
136
- this.urlResolver.resolve(docDefinition.images[image]);
178
+ let url = getExtendedUrl(docDefinition.images[image]);
179
+ this.urlResolver.resolve(url.url, url.headers);
180
+ docDefinition.images[image] = url.url;
181
+ }
182
+ }
183
+ }
184
+
185
+ if (docDefinition.attachments) {
186
+ for (let attachment in docDefinition.attachments) {
187
+ if (docDefinition.attachments.hasOwnProperty(attachment) && docDefinition.attachments[attachment].src) {
188
+ let url = getExtendedUrl(docDefinition.attachments[attachment].src);
189
+ this.urlResolver.resolve(url.url, url.headers);
190
+ docDefinition.attachments[attachment].src = url.url;
191
+ }
192
+ }
193
+ }
194
+
195
+ if (docDefinition.files) {
196
+ for (let file in docDefinition.files) {
197
+ if (docDefinition.files.hasOwnProperty(file) && docDefinition.files[file].src) {
198
+ let url = getExtendedUrl(docDefinition.files[file].src);
199
+ this.urlResolver.resolve(url.url, url.headers);
200
+ docDefinition.files[file].src = url.url;
137
201
  }
138
202
  }
139
203
  }
@@ -180,6 +244,23 @@ function createMetadata(docDefinition) {
180
244
  return info;
181
245
  }
182
246
 
247
+ function embedFiles(docDefinition, pdfKitDoc) {
248
+ if (docDefinition.files) {
249
+ for (const key in docDefinition.files) {
250
+ const file = docDefinition.files[key];
251
+
252
+ if (!file.src) return;
253
+
254
+ if (pdfKitDoc.virtualfs && pdfKitDoc.virtualfs.existsSync(file.src)) {
255
+ file.src = pdfKitDoc.virtualfs.readFileSync(file.src);
256
+ }
257
+
258
+ file.name = file.name || key;
259
+ pdfKitDoc.file(file.src, file);
260
+ }
261
+ }
262
+ }
263
+
183
264
  function calculatePageHeight(pages, margins) {
184
265
  function getItemHeight(item) {
185
266
  if (typeof item.item.getHeight === 'function') {
@@ -187,7 +268,11 @@ function calculatePageHeight(pages, margins) {
187
268
  } else if (item.item._height) {
188
269
  return item.item._height;
189
270
  } else if (item.type === 'vector') {
190
- return item.item.y1 > item.item.y2 ? item.item.y1 : item.item.y2;
271
+ if (typeof item.item.y1 !== 'undefined') {
272
+ return item.item.y1 > item.item.y2 ? item.item.y1 : item.item.y2;
273
+ } else {
274
+ return item.item.h;
275
+ }
191
276
  } else {
192
277
  // TODO: add support for next item types
193
278
  return 0;
package/src/Renderer.js CHANGED
@@ -78,6 +78,9 @@ class Renderer {
78
78
  case 'svg':
79
79
  this.renderSVG(item.item);
80
80
  break;
81
+ case 'attachment':
82
+ this.renderAttachment(item.item);
83
+ break;
81
84
  case 'beginClip':
82
85
  this.beginClip(item.item);
83
86
  break;
@@ -306,6 +309,27 @@ class Renderer {
306
309
  if (image.linkToDestination) {
307
310
  this.pdfDocument.goTo(image.x, image.y, image._width, image._height, image.linkToDestination);
308
311
  }
312
+ if (image.linkToFile) {
313
+ const attachment = this.pdfDocument.provideAttachment(image.linkToFile);
314
+ this.pdfDocument.fileAnnotation(
315
+ image.x,
316
+ image.y,
317
+ image._width,
318
+ image._height,
319
+ attachment,
320
+ // add empty rectangle as file annotation appearance with the same size as the rendered image
321
+ {
322
+ AP: {
323
+ N: {
324
+ Type: 'XObject',
325
+ Subtype: 'Form',
326
+ FormType: 1,
327
+ BBox: [image.x, image.y, image._width, image._height]
328
+ }
329
+ },
330
+ }
331
+ );
332
+ }
309
333
  }
310
334
 
311
335
  renderSVG(svg) {
@@ -326,6 +350,17 @@ class Renderer {
326
350
  SVGtoPDF(this.pdfDocument, svg.svg, svg.x, svg.y, options);
327
351
  }
328
352
 
353
+ renderAttachment(attachment) {
354
+ const file = this.pdfDocument.provideAttachment(attachment.attachment);
355
+
356
+ const options = {};
357
+ if (attachment.icon) {
358
+ options.Name = attachment.icon;
359
+ }
360
+
361
+ this.pdfDocument.fileAnnotation(attachment.x, attachment.y, attachment._width, attachment._height, file, options);
362
+ }
363
+
329
364
  beginClip(rect) {
330
365
  this.pdfDocument.save();
331
366
  this.pdfDocument.addContent(`${rect.x} ${rect.y} ${rect.width} ${rect.height} re`);
@@ -1,12 +1,15 @@
1
1
  import http from 'http';
2
2
  import https from 'https';
3
3
 
4
- const fetchUrl = url => {
4
+ const fetchUrl = (url, headers = {}) => {
5
5
  return new Promise((resolve, reject) => {
6
6
  const parsedUrl = new URL(url);
7
7
  const h = (parsedUrl.protocol === 'https:') ? https : http;
8
+ let options = {
9
+ headers: headers
10
+ };
8
11
 
9
- h.get(url, res => {
12
+ h.get(url, options, res => {
10
13
  if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { // redirect url
11
14
  fetchUrl(res.headers.location).then(buffer => {
12
15
  resolve(buffer);
@@ -34,16 +37,21 @@ class URLResolver {
34
37
  this.resolving = {};
35
38
  }
36
39
 
37
- resolve(url) {
40
+ resolve(url, headers = {}) {
38
41
  if (!this.resolving[url]) {
39
42
  this.resolving[url] = new Promise((resolve, reject) => {
40
43
  if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
41
- fetchUrl(url).then(buffer => {
42
- this.fs.writeFileSync(url, buffer);
44
+ if (this.fs.existsSync(url)) {
45
+ // url was downloaded earlier
43
46
  resolve();
44
- }, result => {
45
- reject(result);
46
- });
47
+ } else {
48
+ fetchUrl(url, headers).then(buffer => {
49
+ this.fs.writeFileSync(url, buffer);
50
+ resolve();
51
+ }, result => {
52
+ reject(result);
53
+ });
54
+ }
47
55
  } else {
48
56
  // cannot be resolved
49
57
  resolve();
@@ -1,7 +1,10 @@
1
- const fetchUrl = url => {
1
+ const fetchUrl = (url, headers = {}) => {
2
2
  return new Promise((resolve, reject) => {
3
3
  const xhr = new XMLHttpRequest();
4
4
  xhr.open('GET', url, true);
5
+ for (let headerName in headers) {
6
+ xhr.setRequestHeader(headerName, headers[headerName]);
7
+ }
5
8
  xhr.responseType = 'arraybuffer';
6
9
 
7
10
  xhr.onreadystatechange = () => {
@@ -46,11 +49,11 @@ class URLBrowserResolver {
46
49
  this.resolving = {};
47
50
  }
48
51
 
49
- resolve(url) {
52
+ resolve(url, headers = {}) {
50
53
  if (!this.resolving[url]) {
51
54
  this.resolving[url] = new Promise((resolve, reject) => {
52
55
  if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
53
- fetchUrl(url).then(buffer => {
56
+ fetchUrl(url, headers).then(buffer => {
54
57
  this.fs.writeFileSync(url, buffer);
55
58
  resolve();
56
59
  }, result => {