UNPKG

pdfmake

Version:

Client/server side PDF printing in pure JavaScript

330 lines (284 loc) 8.65 kB
'use strict'; var isFunction = require('../helpers').isFunction; var isUndefined = require('../helpers').isUndefined; var isNull = require('../helpers').isNull; var FileSaver = require('file-saver'); var saveAs = FileSaver.saveAs; var defaultClientFonts = { Roboto: { normal: 'Roboto-Regular.ttf', bold: 'Roboto-Medium.ttf', italics: 'Roboto-Italic.ttf', bolditalics: 'Roboto-MediumItalic.ttf' } }; function Document(docDefinition, tableLayouts, fonts, vfs) { this.docDefinition = docDefinition; this.tableLayouts = tableLayouts || null; this.fonts = fonts || defaultClientFonts; this.vfs = vfs; } function canCreatePdf() { // Ensure the browser provides the level of support needed try { var arr = new Uint8Array(1) var proto = { foo: function () { return 42 } } Object.setPrototypeOf(proto, Uint8Array.prototype) Object.setPrototypeOf(arr, proto) return arr.foo() === 42 } catch (e) { return false } } Document.prototype._createDoc = function (options, cb) { var getExtendedUrl = function (url) { if (typeof url === 'object') { return { url: url.url, headers: url.headers }; } return { url: url, headers: {} }; }; options = options || {}; if (this.tableLayouts) { options.tableLayouts = this.tableLayouts; } var PdfPrinter = require('../printer'); var printer = new PdfPrinter(this.fonts); require('fs').bindFS(this.vfs); // bind virtual file system to file system if (!isFunction(cb)) { var doc = printer.createPdfKitDocument(this.docDefinition, options); return doc; } var URLBrowserResolver = require('./URLBrowserResolver'); var urlResolver = new URLBrowserResolver(require('fs')); for (var font in this.fonts) { if (this.fonts.hasOwnProperty(font)) { if (this.fonts[font].normal) { if (Array.isArray(this.fonts[font].normal)) { // TrueType Collection var url = getExtendedUrl(this.fonts[font].normal[0]); urlResolver.resolve(url.url, url.headers); this.fonts[font].normal[0] = url.url; } else { var url = getExtendedUrl(this.fonts[font].normal); urlResolver.resolve(url.url, url.headers); this.fonts[font].normal = url.url; } } if (this.fonts[font].bold) { if (Array.isArray(this.fonts[font].bold)) { // TrueType Collection var url = getExtendedUrl(this.fonts[font].bold[0]); urlResolver.resolve(url.url, url.headers); this.fonts[font].bold[0] = url.url; } else { var url = getExtendedUrl(this.fonts[font].bold); urlResolver.resolve(url.url, url.headers); this.fonts[font].bold = url.url; } } if (this.fonts[font].italics) { if (Array.isArray(this.fonts[font].italics)) { // TrueType Collection var url = getExtendedUrl(this.fonts[font].italics[0]); urlResolver.resolve(url.url, url.headers); this.fonts[font].italics[0] = url.url; } else { var url = getExtendedUrl(this.fonts[font].italics); urlResolver.resolve(url.url, url.headers); this.fonts[font].italics = url.url; } } if (this.fonts[font].bolditalics) { if (Array.isArray(this.fonts[font].bolditalics)) { // TrueType Collection var url = getExtendedUrl(this.fonts[font].bolditalics[0]); urlResolver.resolve(url.url, url.headers); this.fonts[font].bolditalics[0] = url.url; } else { var url = getExtendedUrl(this.fonts[font].bolditalics); urlResolver.resolve(url.url, url.headers); this.fonts[font].bolditalics = url.url; } } } } if (this.docDefinition.images) { for (var image in this.docDefinition.images) { if (this.docDefinition.images.hasOwnProperty(image)) { var url = getExtendedUrl(this.docDefinition.images[image]); urlResolver.resolve(url.url, url.headers); this.docDefinition.images[image] = url.url; } } } var _this = this; urlResolver.resolved().then(function () { var doc = printer.createPdfKitDocument(_this.docDefinition, options); cb(doc); }, function (result) { throw result; }); }; Document.prototype._flushDoc = function (doc, callback) { var chunks = []; var result; doc.on('readable', function () { var chunk; while ((chunk = doc.read(9007199254740991)) !== null) { chunks.push(chunk); } }); doc.on('end', function () { result = Buffer.concat(chunks); callback(result, doc._pdfMakePages); }); doc.end(); }; Document.prototype._getPages = function (options, cb) { if (!cb) { throw '_getPages is an async method and needs a callback argument'; } var _this = this; this._createDoc(options, function (doc) { _this._flushDoc(doc, function (ignoreBuffer, pages) { cb(pages); }); }); }; Document.prototype._bufferToBlob = function (buffer) { var blob; try { blob = new Blob([buffer], { type: 'application/pdf' }); } catch (e) { // Old browser which can't handle it without making it an byte array (ie10) if (e.name === 'InvalidStateError') { var byteArray = new Uint8Array(buffer); blob = new Blob([byteArray.buffer], { type: 'application/pdf' }); } } if (!blob) { throw 'Could not generate blob'; } return blob; }; Document.prototype._openWindow = function () { // we have to open the window immediately and store the reference // otherwise popup blockers will stop us var win = window.open('', '_blank'); if (win === null) { throw 'Open PDF in new window blocked by browser'; } return win; }; Document.prototype._openPdf = function (options, win) { if (!win) { win = this._openWindow(); } try { this.getBlob(function (result) { var urlCreator = window.URL || window.webkitURL; var pdfUrl = urlCreator.createObjectURL(result); win.location.href = pdfUrl; /* temporarily disabled if (win !== window) { setTimeout(function () { if (isNull(win.window)) { // is closed by AdBlock window.location.href = pdfUrl; // open in actual window } }, 500); } */ }, options); } catch (e) { win.close(); throw e; } }; Document.prototype.open = function (options, win) { options = options || {}; options.autoPrint = false; win = win || null; this._openPdf(options, win); }; Document.prototype.print = function (options, win) { options = options || {}; options.autoPrint = true; win = win || null; this._openPdf(options, win); }; /** * download(defaultFileName = 'file.pdf', cb = null, options = {}) * or * download(cb, options = {}) */ Document.prototype.download = function (defaultFileName, cb, options) { if (isFunction(defaultFileName)) { if (!isUndefined(cb)) { options = cb; } cb = defaultFileName; defaultFileName = null; } defaultFileName = defaultFileName || 'file.pdf'; this.getBlob(function (result) { saveAs(result, defaultFileName); if (isFunction(cb)) { cb(); } }, options); }; Document.prototype.getBase64 = function (cb, options) { if (!cb) { throw 'getBase64 is an async method and needs a callback argument'; } this.getBuffer(function (buffer) { cb(buffer.toString('base64')); }, options); }; Document.prototype.getDataUrl = function (cb, options) { if (!cb) { throw 'getDataUrl is an async method and needs a callback argument'; } this.getBuffer(function (buffer) { cb('data:application/pdf;base64,' + buffer.toString('base64')); }, options); }; Document.prototype.getBlob = function (cb, options) { if (!cb) { throw 'getBlob is an async method and needs a callback argument'; } var that = this; this.getBuffer(function (result) { var blob = that._bufferToBlob(result); cb(blob); }, options); }; Document.prototype.getBuffer = function (cb, options) { if (!cb) { throw 'getBuffer is an async method and needs a callback argument'; } var _this = this; this._createDoc(options, function (doc) { _this._flushDoc(doc, function (buffer) { cb(buffer); }); }); }; Document.prototype.getStream = function (options, cb) { if (!isFunction(cb)) { var doc = this._createDoc(options); return doc; } this._createDoc(options, function (doc) { cb(doc); }); }; module.exports = { createPdf: function (docDefinition, tableLayouts, fonts, vfs) { if (!canCreatePdf()) { throw 'Your browser does not provide the level of support needed'; } return new Document( docDefinition, tableLayouts || global.pdfMake.tableLayouts, fonts || global.pdfMake.fonts, vfs || global.pdfMake.vfs ); } };