pdfmake 0.3.0-beta.1 → 0.3.0-beta.2
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 +6 -1
- package/README.md +3 -1
- package/build/pdfmake.js +17869 -17667
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- 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 +68 -6
- package/js/Renderer.js +30 -0
- package/js/URLResolver.js +7 -4
- 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 +63 -6
- package/src/Renderer.js +35 -0
- package/src/URLResolver.js +7 -4
- package/src/browser-extensions/URLBrowserResolver.js +6 -3
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;
|
package/js/DocPreprocessor.js
CHANGED
|
@@ -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;
|
package/js/ElementWriter.js
CHANGED
|
@@ -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;
|
package/js/LayoutBuilder.js
CHANGED
|
@@ -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',
|
package/js/PageElementWriter.js
CHANGED
|
@@ -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,27 @@ 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
|
-
|
|
148
|
+
let url = getExtendedUrl(this.fontDescriptors[font].normal);
|
|
149
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
150
|
+
this.fontDescriptors[font].normal = url.url;
|
|
133
151
|
}
|
|
134
152
|
|
|
135
153
|
if (this.fontDescriptors[font].bold) {
|
|
136
|
-
|
|
154
|
+
let url = getExtendedUrl(this.fontDescriptors[font].bold);
|
|
155
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
156
|
+
this.fontDescriptors[font].bold = url.url;
|
|
137
157
|
}
|
|
138
158
|
|
|
139
159
|
if (this.fontDescriptors[font].italics) {
|
|
140
|
-
|
|
160
|
+
let url = getExtendedUrl(this.fontDescriptors[font].italics);
|
|
161
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
162
|
+
this.fontDescriptors[font].italics = url.url;
|
|
141
163
|
}
|
|
142
164
|
|
|
143
165
|
if (this.fontDescriptors[font].bolditalics) {
|
|
144
|
-
|
|
166
|
+
let url = getExtendedUrl(this.fontDescriptors[font].bolditalics);
|
|
167
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
168
|
+
this.fontDescriptors[font].bolditalics = url.url;
|
|
145
169
|
}
|
|
146
170
|
}
|
|
147
171
|
}
|
|
@@ -149,7 +173,29 @@ class PdfPrinter {
|
|
|
149
173
|
if (docDefinition.images) {
|
|
150
174
|
for (let image in docDefinition.images) {
|
|
151
175
|
if (docDefinition.images.hasOwnProperty(image)) {
|
|
152
|
-
|
|
176
|
+
let url = getExtendedUrl(docDefinition.images[image]);
|
|
177
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
178
|
+
docDefinition.images[image] = url.url;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (docDefinition.attachments) {
|
|
184
|
+
for (let attachment in docDefinition.attachments) {
|
|
185
|
+
if (docDefinition.attachments.hasOwnProperty(attachment) && docDefinition.attachments[attachment].src) {
|
|
186
|
+
let url = getExtendedUrl(docDefinition.attachments[attachment].src);
|
|
187
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
188
|
+
docDefinition.attachments[attachment].src = url.url;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (docDefinition.files) {
|
|
194
|
+
for (let file in docDefinition.files) {
|
|
195
|
+
if (docDefinition.files.hasOwnProperty(file) && docDefinition.files[file].src) {
|
|
196
|
+
let url = getExtendedUrl(docDefinition.files[file].src);
|
|
197
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
198
|
+
docDefinition.files[file].src = url.url;
|
|
153
199
|
}
|
|
154
200
|
}
|
|
155
201
|
}
|
|
@@ -199,6 +245,22 @@ function createMetadata(docDefinition) {
|
|
|
199
245
|
return info;
|
|
200
246
|
}
|
|
201
247
|
|
|
248
|
+
function embedFiles(docDefinition, pdfKitDoc) {
|
|
249
|
+
if (docDefinition.files) {
|
|
250
|
+
for (const key in docDefinition.files) {
|
|
251
|
+
const file = docDefinition.files[key];
|
|
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
|
+
|
|
202
264
|
function calculatePageHeight(pages, margins) {
|
|
203
265
|
function getItemHeight(item) {
|
|
204
266
|
if (typeof item.item.getHeight === 'function') {
|
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
|
-
|
|
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,11 +46,11 @@ 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 => {
|
|
53
|
+
fetchUrl(url, headers).then(buffer => {
|
|
51
54
|
this.fs.writeFileSync(url, buffer);
|
|
52
55
|
resolve();
|
|
53
56
|
}, result => {
|
|
@@ -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
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;
|
package/src/DocPreprocessor.js
CHANGED
|
@@ -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;
|
package/src/ElementWriter.js
CHANGED
|
@@ -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;
|
package/src/LayoutBuilder.js
CHANGED
|
@@ -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) {
|
package/src/PDFDocument.js
CHANGED
|
@@ -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',
|
package/src/PageElementWriter.js
CHANGED
|
@@ -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
|
}
|
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,24 @@ 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
|
+
let url = getExtendedUrl(this.fontDescriptors[font].normal);
|
|
130
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
131
|
+
this.fontDescriptors[font].normal = url.url;
|
|
120
132
|
}
|
|
121
133
|
if (this.fontDescriptors[font].bold) {
|
|
122
|
-
|
|
134
|
+
let url = getExtendedUrl(this.fontDescriptors[font].bold);
|
|
135
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
136
|
+
this.fontDescriptors[font].bold = url.url;
|
|
123
137
|
}
|
|
124
138
|
if (this.fontDescriptors[font].italics) {
|
|
125
|
-
|
|
139
|
+
let url = getExtendedUrl(this.fontDescriptors[font].italics);
|
|
140
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
141
|
+
this.fontDescriptors[font].italics = url.url;
|
|
126
142
|
}
|
|
127
143
|
if (this.fontDescriptors[font].bolditalics) {
|
|
128
|
-
|
|
144
|
+
let url = getExtendedUrl(this.fontDescriptors[font].bolditalics);
|
|
145
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
146
|
+
this.fontDescriptors[font].bolditalics = url.url;
|
|
129
147
|
}
|
|
130
148
|
}
|
|
131
149
|
}
|
|
@@ -133,7 +151,29 @@ class PdfPrinter {
|
|
|
133
151
|
if (docDefinition.images) {
|
|
134
152
|
for (let image in docDefinition.images) {
|
|
135
153
|
if (docDefinition.images.hasOwnProperty(image)) {
|
|
136
|
-
|
|
154
|
+
let url = getExtendedUrl(docDefinition.images[image]);
|
|
155
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
156
|
+
docDefinition.images[image] = url.url;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (docDefinition.attachments) {
|
|
162
|
+
for (let attachment in docDefinition.attachments) {
|
|
163
|
+
if (docDefinition.attachments.hasOwnProperty(attachment) && docDefinition.attachments[attachment].src) {
|
|
164
|
+
let url = getExtendedUrl(docDefinition.attachments[attachment].src);
|
|
165
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
166
|
+
docDefinition.attachments[attachment].src = url.url;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (docDefinition.files) {
|
|
172
|
+
for (let file in docDefinition.files) {
|
|
173
|
+
if (docDefinition.files.hasOwnProperty(file) && docDefinition.files[file].src) {
|
|
174
|
+
let url = getExtendedUrl(docDefinition.files[file].src);
|
|
175
|
+
this.urlResolver.resolve(url.url, url.headers);
|
|
176
|
+
docDefinition.files[file].src = url.url;
|
|
137
177
|
}
|
|
138
178
|
}
|
|
139
179
|
}
|
|
@@ -180,6 +220,23 @@ function createMetadata(docDefinition) {
|
|
|
180
220
|
return info;
|
|
181
221
|
}
|
|
182
222
|
|
|
223
|
+
function embedFiles(docDefinition, pdfKitDoc) {
|
|
224
|
+
if (docDefinition.files) {
|
|
225
|
+
for (const key in docDefinition.files) {
|
|
226
|
+
const file = docDefinition.files[key];
|
|
227
|
+
|
|
228
|
+
if (!file.src) return;
|
|
229
|
+
|
|
230
|
+
if (pdfKitDoc.virtualfs && pdfKitDoc.virtualfs.existsSync(file.src)) {
|
|
231
|
+
file.src = pdfKitDoc.virtualfs.readFileSync(file.src);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
file.name = file.name || key;
|
|
235
|
+
pdfKitDoc.file(file.src, file);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
183
240
|
function calculatePageHeight(pages, margins) {
|
|
184
241
|
function getItemHeight(item) {
|
|
185
242
|
if (typeof item.item.getHeight === 'function') {
|