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/CHANGELOG.md +13 -1
- package/LICENSE +1 -1
- package/README.md +3 -1
- package/build/pdfmake.js +18834 -19020
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/build/vfs_fonts.js +4 -4
- package/fonts/Roboto/Roboto-Italic.ttf +0 -0
- package/fonts/Roboto/Roboto-Medium.ttf +0 -0
- package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
- package/fonts/Roboto/Roboto-Regular.ttf +0 -0
- package/js/DocMeasure.js +8 -0
- package/js/DocPreprocessor.js +6 -0
- package/js/ElementWriter.js +23 -0
- package/js/LayoutBuilder.js +7 -0
- package/js/PDFDocument.js +28 -1
- package/js/PageElementWriter.js +4 -0
- package/js/Printer.js +101 -7
- package/js/Renderer.js +30 -0
- package/js/URLResolver.js +16 -8
- package/js/browser-extensions/URLBrowserResolver.js +8 -3
- package/package.json +1 -1
- package/src/DocMeasure.js +9 -0
- package/src/DocPreprocessor.js +6 -0
- package/src/ElementWriter.js +26 -0
- package/src/LayoutBuilder.js +7 -0
- package/src/PDFDocument.js +27 -1
- package/src/PageElementWriter.js +4 -0
- package/src/Printer.js +92 -7
- package/src/Renderer.js +35 -0
- package/src/URLResolver.js +16 -8
- package/src/browser-extensions/URLBrowserResolver.js +6 -3
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`);
|
package/src/URLResolver.js
CHANGED
|
@@ -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
|
-
|
|
42
|
-
|
|
44
|
+
if (this.fs.existsSync(url)) {
|
|
45
|
+
// url was downloaded earlier
|
|
43
46
|
resolve();
|
|
44
|
-
}
|
|
45
|
-
|
|
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 => {
|