From 182c59b8ffe0c9ea7abc6fd26512dad5df55c140 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:08:50 +0200
Subject: [PATCH 01/13] Delete standard.spec.js
---
tests/addhtml/standard.spec.js | 21 ---------------------
1 file changed, 21 deletions(-)
delete mode 100644 tests/addhtml/standard.spec.js
diff --git a/tests/addhtml/standard.spec.js b/tests/addhtml/standard.spec.js
deleted file mode 100644
index e0aeafb9e..000000000
--- a/tests/addhtml/standard.spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-
-/* global describe, it, jsPDF, comparePdf, expect */
-/**
- * Standard spec tests
- */
-
-describe('Plugin: addhtml', () => {
-
- xit('should add HTML to the document', (done) => {
- document.body.innerHTML = 'This is a test
'
- const doc = new jsPDF('p','pt','a4')
-
- doc.addHTML(document.body,function() {
- setTimeout(() => {
- doc.output('datauri')
- comparePdf(doc.output('datauri'), 'html-output.pdf', 'addhtml')
- done()
- }, 1000)
- })
- })
-})
From 0942efea715debbad19f2dffcc3358846a06d527 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:09:04 +0200
Subject: [PATCH 02/13] Delete html-output.pdf
---
tests/addhtml/reference/html-output.pdf | Bin 20991 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 tests/addhtml/reference/html-output.pdf
diff --git a/tests/addhtml/reference/html-output.pdf b/tests/addhtml/reference/html-output.pdf
deleted file mode 100644
index af0ecd8254724d49b27904423684f3a9008d5d9a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 20991
zcmeI4*;5-w5QkR>AT8LIz;=$8j1OX*6s%^oI&e`=A<43FoWd3)cI?W-A}x3+X&0oG
zja`+h_&%QE`^ZatA5XroN>!?6{;~9|guxOa2UK3t16qw*y*)kO^tRr9-Mcf{UfLIx
zqa;G?u}OJgKp8zUWe{bzK4HjkEgP0YD14ifm7GzrtL3~=A!^O=jZrZ5ls!WZM8FX1
zkM*fZlGJElvi}EJN!ykKcUOq!dT-q-8&*LqB0kp_+htf2&Os8>;M}d&BD_YmJ_?!iMPRNb`VvW!FA-%ZLNYelBVyMB)K?KnH*KjRD_@(13OOJ)
zoFi_QRk1^PF1^^?jVZliWMLc14x@O;aLl~!;!%W6R<>DryI@)q%3jkNv?}K8XIUAk
zjyZtQb*6KX|qG^eYzoc`?wl8de&Hn1G4^e?bV8Y<5;%1h!y
zMH$sg;{D0i123JvsLel(z8qMnca@rJ3UpSYGSV0^WXV(c>OAc
zc4mjNlE))S9{7{M_KTF3d|olc)d$1h>K7x>+S<|@49IdY5Ddy4t2*TNmF>acitvh+
zt3si0NbczD>I`+kJX8zg5%>E10k}2P9&88uKO7L|Cn+58@}K?fKF@l|8}|6Z9?$0;%Z2m%v#S_W?E$Pg*?Dic)
zJ4Z&p{ci8R@Au~m#`wfRbF$)84;`L4a+IB5C)p`>nw?>1**SKeU1XQoWp;&KW!Kns
zc7xqyx7i(bm)&Fc*#q{FJz|g9GxnUlU@zG#_L{w6Z`nJ3oS)z)`6+&ypW$cuIewmB
zLPyZj!%&mZuI{1Jc5pYmt?Ie)=l@>l#df5YGMcQslb
z$yb8~*BY*7T4A8&^}~U+30fZSVR-q%{+4yLwR3P!n?BvO9$*DlrvxtnE4U$=<4@L%
zmH7pE?M98?>gG=cF&Eh1xwlK5|MKDXKV9tp2V00|%g
zB!C2v01`j~NB{{S0VIF~kN^@u0!RP}AOR$R1dsp{Kmter2_OL^fCP{L5
z3HU(I0nNYD;p(Tz?aUh2F|p$9w-$lb)h6TIZ&H(m6UQqFK$lQjm}Ayx%)0u^B{lJGg%Qk
zr+qWMCA|WINSi@K2{i5;)3!3YW00QA7TTXoP?bh%vprR|1MC
zX&nTu>>yUPSOmVpcb9&|uEHS1>_4!H4*;aWMg_PAo0`d#KxL!6tEvu%gC^#TPwWR2UztxLC7D~?`v
R+%u+{7E|T!?rp=_KLD+mspkLy
From 04287e6b96db11c55b84855c2fbf23ea66edf07c Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:09:52 +0200
Subject: [PATCH 03/13] Rename plugins/addhtml.js to deprecated/addhtml.js
---
{plugins => deprecated}/addhtml.js | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {plugins => deprecated}/addhtml.js (100%)
diff --git a/plugins/addhtml.js b/deprecated/addhtml.js
similarity index 100%
rename from plugins/addhtml.js
rename to deprecated/addhtml.js
From 1dc2d1ba5301b4ca00e87ad58c10102c03b8e1c2 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:10:29 +0200
Subject: [PATCH 04/13] Rename plugins/from_html.js to deprecated/from_html.js
---
{plugins => deprecated}/from_html.js | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {plugins => deprecated}/from_html.js (100%)
diff --git a/plugins/from_html.js b/deprecated/from_html.js
similarity index 100%
rename from plugins/from_html.js
rename to deprecated/from_html.js
From 1c8897d0b84315d2be34d2ad5209b3bc45cf83dd Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:11:13 +0200
Subject: [PATCH 05/13] Delete test_from_html.html
---
examples/test_from_html.html | 78 ------------------------------------
1 file changed, 78 deletions(-)
delete mode 100644 examples/test_from_html.html
diff --git a/examples/test_from_html.html b/examples/test_from_html.html
deleted file mode 100644
index 26912c6f9..000000000
--- a/examples/test_from_html.html
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-Test HTML
-
-
-
-
-
-
-
-
-
-
-
From 93a8a2eb8eeaef4614becc87aa27de9b5c1240e0 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Fri, 7 Sep 2018 14:11:46 +0200
Subject: [PATCH 06/13] Update main_plugins.js
---
main_plugins.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/main_plugins.js b/main_plugins.js
index 7ddbcff47..30d83e843 100644
--- a/main_plugins.js
+++ b/main_plugins.js
@@ -1,5 +1,4 @@
import './plugins/acroform';
-import './plugins/addhtml';
import './plugins/addimage';
import './plugins/annotations';
import './plugins/arabic';
@@ -7,7 +6,6 @@ import './plugins/autoprint';
import './plugins/canvas';
import './plugins/cell';
import './plugins/context2d';
-import './plugins/from_html';
import './plugins/javascript';
import './plugins/outline';
import './plugins/png_support';
@@ -22,4 +20,4 @@ import './plugins/total_pages';
import './plugins/viewerpreferences';
import './plugins/xmp_metadata';
import './plugins/utf8';
-import './plugins/vfs';
\ No newline at end of file
+import './plugins/vfs';
From 25d9e3a491b1231eda36b10bbc5b87a20a8058c1 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Sat, 8 Sep 2018 04:45:35 +0430
Subject: [PATCH 07/13] Add files via upload
---
plugins/html.js | 785 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 785 insertions(+)
create mode 100644 plugins/html.js
diff --git a/plugins/html.js b/plugins/html.js
new file mode 100644
index 000000000..f19bc2762
--- /dev/null
+++ b/plugins/html.js
@@ -0,0 +1,785 @@
+/**
+ * jsPDF html PlugIn
+ * Copyright (c) 2018 Erik Koopmans
+ * Released under the MIT License.
+ *
+ * Licensed under the MIT License.
+ * http://opensource.org/licenses/mit-license
+ */
+
+(function (jsPDFAPI, global) {
+ 'use strict';
+
+ /**
+ * Determine the type of a variable/object.
+ *
+ * @private
+ * @ignore
+ */
+ var objType = function(obj) {
+ var type = typeof obj;
+ if (type === 'undefined') return 'undefined';
+ else if (type === 'string' || obj instanceof String) return 'string';
+ else if (type === 'number' || obj instanceof Number) return 'number';
+ else if (type === 'function' || obj instanceof Function) return 'function';
+ else if (!!obj && obj.constructor === Array) return 'array';
+ else if (obj && obj.nodeType === 1) return 'element';
+ else if (type === 'object') return 'object';
+ else return 'unknown';
+ };
+
+ /**
+ * Create an HTML element with optional className, innerHTML, and style.
+ *
+ * @private
+ * @ignore
+ */
+ var createElement = function(tagName, opt) {
+ var el = document.createElement(tagName);
+ if (opt.className) el.className = opt.className;
+ if (opt.innerHTML) {
+ el.innerHTML = opt.innerHTML;
+ var scripts = el.getElementsByTagName('script');
+ for (var i = scripts.length; i-- > 0; null) {
+ scripts[i].parentNode.removeChild(scripts[i]);
+ }
+ }
+ for (var key in opt.style) {
+ el.style[key] = opt.style[key];
+ }
+ return el;
+ };
+
+ /**
+ * Deep-clone a node and preserve contents/properties.
+ *
+ * @private
+ * @ignore
+ */
+ var cloneNode = function(node, javascriptEnabled) {
+ // Recursively clone the node.
+ var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
+ clone.appendChild(cloneNode(child, javascriptEnabled));
+ }
+ }
+
+ if (node.nodeType === 1) {
+ // Preserve contents/properties of special nodes.
+ if (node.nodeName === 'CANVAS') {
+ clone.width = node.width;
+ clone.height = node.height;
+ clone.getContext('2d').drawImage(node, 0, 0);
+ } else if (node.nodeName === 'TEXTAREA' || node.nodeName === 'SELECT') {
+ clone.value = node.value;
+ }
+
+ // Preserve the node's scroll position when it loads.
+ clone.addEventListener('load', function() {
+ clone.scrollTop = node.scrollTop;
+ clone.scrollLeft = node.scrollLeft;
+ }, true);
+ }
+
+ // Return the cloned node.
+ return clone;
+ }
+
+ /**
+ * Convert units using the conversion value 'k' from jsPDF.
+ *
+ * @private
+ * @ignore
+ */
+ var unitConvert = function(obj, k) {
+ var newObj = {};
+ for (var key in obj) {
+ newObj[key] = obj[key] * 72 / 96 / k;
+ }
+ return newObj;
+ };
+
+
+
+ /* ----- CONSTRUCTOR ----- */
+
+ var Worker = function Worker(opt) {
+ // Create the root parent for the proto chain, and the starting Worker.
+ var root = Object.assign(Worker.convert(Promise.resolve()),
+ JSON.parse(JSON.stringify(Worker.template)));
+ var self = Worker.convert(Promise.resolve(), root);
+
+ // Set progress, optional settings, and return.
+ self = self.setProgress(1, Worker, 1, [Worker]);
+ self = self.set(opt);
+ return self;
+ };
+
+ // Boilerplate for subclassing Promise.
+ Worker.prototype = Object.create(Promise.prototype);
+ Worker.prototype.constructor = Worker;
+
+ // Converts/casts promises into Workers.
+ Worker.convert = function convert(promise, inherit) {
+ // Uses prototypal inheritance to receive changes made to ancestors' properties.
+ promise.__proto__ = inherit || Worker.prototype;
+ return promise;
+ };
+
+ Worker.template = {
+ prop: {
+ src: null,
+ container: null,
+ overlay: null,
+ canvas: null,
+ img: null,
+ pdf: null,
+ pageSize: null,
+ callback: function () {}
+ },
+ progress: {
+ val: 0,
+ state: null,
+ n: 0,
+ stack: []
+ },
+ opt: {
+ filename: 'file.pdf',
+ margin: [0,0,0,0],
+ enableLinks: true,
+ html2canvas: {
+ async: true,
+ allowTaint: true,
+ backgroundColor: '#ffffff',
+ imageTimeout: 15000,
+ logging: true,
+ proxy: null,
+ removeContainer: true,
+ foreignObjectRendering: false,
+ useCORS: false
+ },
+ jsPDF: {}
+ }
+ };
+
+ /* ----- FROM / TO ----- */
+
+ Worker.prototype.from = function from(src, type) {
+ function getType(src) {
+ switch (objType(src)) {
+ case 'string': return 'string';
+ case 'element': return src.nodeName.toLowerCase === 'canvas' ? 'canvas' : 'element';
+ default: return 'unknown';
+ }
+ }
+
+ return this.then(function from_main() {
+ type = type || getType(src);
+ switch (type) {
+ case 'string': return this.set({ src: createElement('div', {innerHTML: src}) });
+ case 'element': return this.set({ src: src });
+ case 'canvas': return this.set({ canvas: src });
+ case 'img': return this.set({ img: src });
+ default: return this.error('Unknown source type.');
+ }
+ });
+ };
+
+ Worker.prototype.to = function to(target) {
+ // Route the 'to' request to the appropriate method.
+ switch (target) {
+ case 'container':
+ return this.toContainer();
+ case 'canvas':
+ return this.toCanvas();
+ case 'img':
+ return this.toImg();
+ case 'pdf':
+ return this.toPdf();
+ default:
+ return this.error('Invalid target.');
+ }
+ };
+
+ Worker.prototype.toContainer = function toContainer() {
+ // Set up function prerequisites.
+ var prereqs = [function checkSrc() {
+ return this.prop.src || this.error('Cannot duplicate - no source HTML.');
+ }, function checkPageSize() {
+ return this.prop.pageSize || this.setPageSize();
+ }];
+ return this.thenList(prereqs).then(function toContainer_main() {
+ // Define the CSS styles for the container and its overlay parent.
+ var overlayCSS = {
+ position: 'fixed',
+ overflow: 'hidden',
+ zIndex: 1000,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ top: 0,
+ backgroundColor: 'rgba(0,0,0,0.8)'
+ };
+ var containerCSS = {
+ position: 'absolute',
+ display: 'inline-block',
+ width: this.prop.pageSize.inner.width + this.prop.pageSize.unit,
+ left: 0,
+ right: 0,
+ top: 0,
+ height: 'auto',
+ margin: 'auto',
+ backgroundColor: 'white'
+ }; // Set the overlay to hidden (could be changed in the future to provide a print preview).
+
+ overlayCSS.opacity = 0; // Create and attach the elements.
+
+ var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled);
+ this.prop.overlay = createElement('div', {
+ className: 'html2pdf__overlay',
+ style: overlayCSS
+ });
+ this.prop.container = createElement('div', {
+ className: 'html2pdf__container',
+ style: containerCSS
+ });
+ this.prop.container.appendChild(source);
+
+ this.prop.container.firstChild.appendChild(createElement('div', {
+ style: {
+ clear: 'both'
+ }
+ }));
+ this.prop.container.style.float = 'none';
+ this.prop.overlay.appendChild(this.prop.container);
+ document.body.appendChild(this.prop.overlay);
+ });
+ };
+
+ Worker.prototype.toCanvas = function toCanvas() {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkContainer() { return document.body.contains(this.prop.container)
+ || this.toContainer(); }
+ ];
+
+ // Fulfill prereqs then create the canvas.
+ return this.thenList(prereqs).then(function toCanvas_main() {
+ // Handle old-fashioned 'onrendered' argument.
+ var options = Object.assign({}, this.opt.html2canvas);
+ delete options.onrendered;
+
+ return html2canvas(this.prop.container, options);
+ }).then(function toCanvas_post(canvas) {
+ // Handle old-fashioned 'onrendered' argument.
+ var onRendered = this.opt.html2canvas.onrendered || function () {};
+ onRendered(canvas);
+
+ this.prop.canvas = canvas;
+ document.body.removeChild(this.prop.overlay);
+ });
+ };
+
+ Worker.prototype.toContext2d = function toContext2d() {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkContainer() { return document.body.contains(this.prop.container)
+ || this.toContainer(); }
+ ];
+
+ // Fulfill prereqs then create the canvas.
+ return this.thenList(prereqs).then(function toContext2d_main() {
+ // Handle old-fashioned 'onrendered' argument.
+
+ var pdf = this.opt.jsPDF;
+ var options = Object.assign({}, this.opt.html2canvas);
+ delete options.onrendered;
+
+ pdf.annotations = {
+ _nameMap: [],
+ createAnnotation: function createAnnotation(href, bounds) {
+ var x = pdf.context2d._wrapX(bounds.left);
+
+ var y = pdf.context2d._wrapY(bounds.top);
+
+ var page = pdf.context2d._page(bounds.top);
+
+ var options;
+ var index = href.indexOf('#');
+
+ if (index >= 0) {
+ options = {
+ name: href.substring(index + 1)
+ };
+ } else {
+ options = {
+ url: href
+ };
+ }
+
+ pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options);
+ },
+ setName: function setName(name, bounds) {
+ var x = pdf.context2d._wrapX(bounds.left);
+
+ var y = pdf.context2d._wrapY(bounds.top);
+
+ var page = pdf.context2d._page(bounds.top);
+
+ this._nameMap[name] = {
+ page: page,
+ x: x,
+ y: y
+ };
+ }
+ };
+
+ pdf.context2d._pageBreakAt = function (y) {
+ this.pageBreaks.push(y);
+ };
+
+ pdf.context2d._gotoPage = function (pageOneBased) {
+ while (pdf.internal.getNumberOfPages() < pageOneBased) {
+ pdf.addPage();
+ }
+
+ pdf.setPage(pageOneBased);
+ };
+
+ return html2canvas(this.prop.container, options);
+ }).then(function toCanvas_post(canvas) {
+ // Handle old-fashioned 'onrendered' argument.
+ var onRendered = this.opt.html2canvas.onrendered || function () {};
+ onRendered(canvas);
+
+ this.prop.canvas = canvas;
+ document.body.removeChild(this.prop.overlay);
+ });
+ };
+
+ Worker.prototype.toImg = function toImg() {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
+ ];
+
+ // Fulfill prereqs then create the image.
+ return this.thenList(prereqs).then(function toImg_main() {
+ var imgData = this.prop.canvas.toDataURL('image/' + this.opt.image.type, this.opt.image.quality);
+ this.prop.img = document.createElement('img');
+ this.prop.img.src = imgData;
+ });
+ };
+
+ Worker.prototype.toPdf = function toPdf() {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkContext2d() { return this.toContext2d(); }
+ //function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
+ ];
+
+ // Fulfill prereqs then create the image.
+ return this.thenList(prereqs).then(function toPdf_main() {
+ // Create local copies of frequently used properties.
+ this.prop.pdf = this.prop.pdf || this.opt.jsPDF;
+ });
+ };
+
+
+ /* ----- OUTPUT / SAVE ----- */
+
+ Worker.prototype.output = function output(type, options, src) {
+ // Redirect requests to the correct function (outputPdf / outputImg).
+ src = src || 'pdf';
+ if (src.toLowerCase() === 'img' || src.toLowerCase() === 'image') {
+ return this.outputImg(type, options);
+ } else {
+ return this.outputPdf(type, options);
+ }
+ };
+
+ Worker.prototype.outputPdf = function outputPdf(type, options) {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkPdf() { return this.prop.pdf || this.toPdf(); }
+ ];
+
+ // Fulfill prereqs then perform the appropriate output.
+ return this.thenList(prereqs).then(function outputPdf_main() {
+ /* Currently implemented output types:
+ * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992
+ * save(options), arraybuffer, blob, bloburi/bloburl,
+ * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl
+ */
+ return this.prop.pdf.output(type, options);
+ });
+ };
+
+ Worker.prototype.outputImg = function outputImg(type, options) {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkImg() { return this.prop.img || this.toImg(); }
+ ];
+
+ // Fulfill prereqs then perform the appropriate output.
+ return this.thenList(prereqs).then(function outputImg_main() {
+ switch (type) {
+ case undefined:
+ case 'img':
+ return this.prop.img;
+ case 'datauristring':
+ case 'dataurlstring':
+ return this.prop.img.src;
+ case 'datauri':
+ case 'dataurl':
+ return document.location.href = this.prop.img.src;
+ default:
+ throw 'Image output type "' + type + '" is not supported.';
+ }
+ });
+ };
+
+ Worker.prototype.save = function save(filename) {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkPdf() { return this.prop.pdf || this.toPdf(); }
+ ];
+
+ // Fulfill prereqs, update the filename (if provided), and save the PDF.
+ return this.thenList(prereqs).set(
+ filename ? { filename: filename } : null
+ ).then(function save_main() {
+ this.prop.pdf.save(this.opt.filename);
+ });
+ };
+
+ Worker.prototype.doCallback = function doCallback(filename) {
+ // Set up function prerequisites.
+ var prereqs = [
+ function checkPdf() { return this.prop.pdf || this.toPdf(); }
+ ];
+
+ // Fulfill prereqs, update the filename (if provided), and save the PDF.
+ return this.thenList(prereqs)
+ .then(function doCallback_main() {
+ this.prop.callback(this.prop.pdf);
+ });
+ };
+
+ /* ----- SET / GET ----- */
+
+ Worker.prototype.set = function set(opt) {
+ // TODO: Implement ordered pairs?
+
+ // Silently ignore invalid or empty input.
+ if (objType(opt) !== 'object') {
+ return this;
+ }
+
+ // Build an array of setter functions to queue.
+ var fns = Object.keys(opt || {}).map(function (key) {
+ if (key in Worker.template.prop) {
+ // Set pre-defined properties.
+ return function set_prop() { this.prop[key] = opt[key]; }
+ } else {
+ switch (key) {
+ case 'margin':
+ return this.setMargin.bind(this, opt.margin);
+ case 'jsPDF':
+ return function set_jsPDF() { this.opt.jsPDF = opt.jsPDF; return this.setPageSize(); }
+ case 'pageSize':
+ return this.setPageSize.bind(this, opt.pageSize);
+ default:
+ // Set any other properties in opt.
+ return function set_opt() { this.opt[key] = opt[key] };
+ }
+ }
+ }, this);
+
+ // Set properties within the promise chain.
+ return this.then(function set_main() {
+ return this.thenList(fns);
+ });
+ };
+
+ Worker.prototype.get = function get(key, cbk) {
+ return this.then(function get_main() {
+ // Fetch the requested property, either as a predefined prop or in opt.
+ var val = (key in Worker.template.prop) ? this.prop[key] : this.opt[key];
+ return cbk ? cbk(val) : val;
+ });
+ };
+
+ Worker.prototype.setMargin = function setMargin(margin) {
+ return this.then(function setMargin_main() {
+ // Parse the margin property.
+ switch (objType(margin)) {
+ case 'number':
+ margin = [margin, margin, margin, margin];
+ case 'array':
+ if (margin.length === 2) {
+ margin = [margin[0], margin[1], margin[0], margin[1]];
+ }
+ if (margin.length === 4) {
+ break;
+ }
+ default:
+ return this.error('Invalid margin array.');
+ }
+
+ // Set the margin property, then update pageSize.
+ this.opt.margin = margin;
+ }).then(this.setPageSize);
+ }
+
+ Worker.prototype.setPageSize = function setPageSize(pageSize) {
+ function toPx(val, k) {
+ return Math.floor(val * k / 72 * 96);
+ }
+
+ return this.then(function setPageSize_main() {
+ // Retrieve page-size based on jsPDF settings, if not explicitly provided.
+ pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF);
+
+ // Add 'inner' field if not present.
+ if (!pageSize.hasOwnProperty('inner')) {
+ pageSize.inner = {
+ width: pageSize.width - this.opt.margin[1] - this.opt.margin[3],
+ height: pageSize.height - this.opt.margin[0] - this.opt.margin[2]
+ };
+ pageSize.inner.px = {
+ width: toPx(pageSize.inner.width, pageSize.k),
+ height: toPx(pageSize.inner.height, pageSize.k)
+ };
+ pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
+ }
+
+ // Attach pageSize to this.
+ this.prop.pageSize = pageSize;
+ });
+ }
+
+ Worker.prototype.setProgress = function setProgress(val, state, n, stack) {
+ // Immediately update all progress values.
+ if (val != null) this.progress.val = val;
+ if (state != null) this.progress.state = state;
+ if (n != null) this.progress.n = n;
+ if (stack != null) this.progress.stack = stack;
+ this.progress.ratio = this.progress.val / this.progress.state;
+
+ // Return this for command chaining.
+ return this;
+ };
+
+ Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) {
+ // Immediately update all progress values, using setProgress.
+ return this.setProgress(
+ val ? this.progress.val + val : null,
+ state ? state : null,
+ n ? this.progress.n + n : null,
+ stack ? this.progress.stack.concat(stack) : null
+ );
+ };
+
+ /* ----- PROMISE MAPPING ----- */
+
+ Worker.prototype.then = function then(onFulfilled, onRejected) {
+ // Wrap `this` for encapsulation.
+ var self = this;
+
+ return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) {
+ // Update progress while queuing, calling, and resolving `then`.
+ self.updateProgress(null, null, 1, [onFulfilled]);
+ return Promise.prototype.then.call(this, function then_pre(val) {
+ self.updateProgress(null, onFulfilled);
+ return val;
+ }).then(onFulfilled, onRejected).then(function then_post(val) {
+ self.updateProgress(1);
+ return val;
+ });
+ });
+ };
+
+ Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) {
+ // Handle optional thenBase parameter.
+ thenBase = thenBase || Promise.prototype.then;
+
+ // Wrap `this` for encapsulation and bind it to the promise handlers.
+ var self = this;
+ if (onFulfilled) { onFulfilled = onFulfilled.bind(self); }
+ if (onRejected) { onRejected = onRejected.bind(self); }
+
+ // Cast self into a Promise to avoid polyfills recursively defining `then`.
+ var isNative = Promise.toString().indexOf('[native code]') !== -1 && Promise.name === 'Promise';
+ var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype);
+
+ // Return the promise, after casting it into a Worker and preserving props.
+ var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected);
+ return Worker.convert(returnVal, self.__proto__);
+ };
+
+ Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) {
+ // Call `then` and return a standard promise (exits the Worker chain).
+ return Promise.prototype.then.call(this, onFulfilled, onRejected);
+ };
+
+ Worker.prototype.thenList = function thenList(fns) {
+ // Queue a series of promise 'factories' into the promise chain.
+ var self = this;
+ fns.forEach(function thenList_forEach(fn) {
+ self = self.thenCore(fn);
+ });
+ return self;
+ };
+
+ Worker.prototype['catch'] = function (onRejected) {
+ // Bind `this` to the promise handler, call `catch`, and return a Worker.
+ if (onRejected) { onRejected = onRejected.bind(this); }
+ var returnVal = Promise.prototype['catch'].call(this, onRejected);
+ return Worker.convert(returnVal, this);
+ };
+
+ Worker.prototype.catchExternal = function catchExternal(onRejected) {
+ // Call `catch` and return a standard promise (exits the Worker chain).
+ return Promise.prototype['catch'].call(this, onRejected);
+ };
+
+ Worker.prototype.error = function error(msg) {
+ // Throw the error in the Promise chain.
+ return this.then(function error_main() {
+ throw new Error(msg);
+ });
+ };
+
+
+ /* ----- ALIASES ----- */
+
+ Worker.prototype.using = Worker.prototype.set;
+ Worker.prototype.saveAs = Worker.prototype.save;
+ Worker.prototype.export = Worker.prototype.output;
+ Worker.prototype.run = Worker.prototype.then;
+
+ // Get dimensions of a PDF page, as determined by jsPDF.
+ jsPDF.getPageSize = function(orientation, unit, format) {
+ // Decode options object
+ if (typeof orientation === 'object') {
+ var options = orientation;
+ orientation = options.orientation;
+ unit = options.unit || unit;
+ format = options.format || format;
+ }
+
+ // Default options
+ unit = unit || 'mm';
+ format = format || 'a4';
+ orientation = ('' + (orientation || 'P')).toLowerCase();
+ var format_as_string = ('' + format).toLowerCase();
+
+ // Size in pt of various paper formats
+ var pageFormats = {
+ 'a0' : [2383.94, 3370.39], 'a1' : [1683.78, 2383.94],
+ 'a2' : [1190.55, 1683.78], 'a3' : [ 841.89, 1190.55],
+ 'a4' : [ 595.28, 841.89], 'a5' : [ 419.53, 595.28],
+ 'a6' : [ 297.64, 419.53], 'a7' : [ 209.76, 297.64],
+ 'a8' : [ 147.40, 209.76], 'a9' : [ 104.88, 147.40],
+ 'a10' : [ 73.70, 104.88], 'b0' : [2834.65, 4008.19],
+ 'b1' : [2004.09, 2834.65], 'b2' : [1417.32, 2004.09],
+ 'b3' : [1000.63, 1417.32], 'b4' : [ 708.66, 1000.63],
+ 'b5' : [ 498.90, 708.66], 'b6' : [ 354.33, 498.90],
+ 'b7' : [ 249.45, 354.33], 'b8' : [ 175.75, 249.45],
+ 'b9' : [ 124.72, 175.75], 'b10' : [ 87.87, 124.72],
+ 'c0' : [2599.37, 3676.54], 'c1' : [1836.85, 2599.37],
+ 'c2' : [1298.27, 1836.85], 'c3' : [ 918.43, 1298.27],
+ 'c4' : [ 649.13, 918.43], 'c5' : [ 459.21, 649.13],
+ 'c6' : [ 323.15, 459.21], 'c7' : [ 229.61, 323.15],
+ 'c8' : [ 161.57, 229.61], 'c9' : [ 113.39, 161.57],
+ 'c10' : [ 79.37, 113.39], 'dl' : [ 311.81, 623.62],
+ 'letter' : [612, 792],
+ 'government-letter' : [576, 756],
+ 'legal' : [612, 1008],
+ 'junior-legal' : [576, 360],
+ 'ledger' : [1224, 792],
+ 'tabloid' : [792, 1224],
+ 'credit-card' : [153, 243]
+ };
+
+ // Unit conversion
+ switch (unit) {
+ case 'pt': var k = 1; break;
+ case 'mm': var k = 72 / 25.4; break;
+ case 'cm': var k = 72 / 2.54; break;
+ case 'in': var k = 72; break;
+ case 'px': var k = 72 / 96; break;
+ case 'pc': var k = 12; break;
+ case 'em': var k = 12; break;
+ case 'ex': var k = 6; break;
+ default:
+ throw ('Invalid unit: ' + unit);
+ }
+
+ // Dimensions are stored as user units and converted to points on output
+ if (pageFormats.hasOwnProperty(format_as_string)) {
+ var pageHeight = pageFormats[format_as_string][1] / k;
+ var pageWidth = pageFormats[format_as_string][0] / k;
+ } else {
+ try {
+ var pageHeight = format[1];
+ var pageWidth = format[0];
+ } catch (err) {
+ throw new Error('Invalid format: ' + format);
+ }
+ }
+
+ // Handle page orientation
+ if (orientation === 'p' || orientation === 'portrait') {
+ orientation = 'p';
+ if (pageWidth > pageHeight) {
+ var tmp = pageWidth;
+ pageWidth = pageHeight;
+ pageHeight = tmp;
+ }
+ } else if (orientation === 'l' || orientation === 'landscape') {
+ orientation = 'l';
+ if (pageHeight > pageWidth) {
+ var tmp = pageWidth;
+ pageWidth = pageHeight;
+ pageHeight = tmp;
+ }
+ } else {
+ throw('Invalid orientation: ' + orientation);
+ }
+
+ // Return information (k is the unit conversion ratio from pts)
+ var info = { 'width': pageWidth, 'height': pageHeight, 'unit': unit, 'k': k };
+ return info;
+ };
+
+ /**
+ * Generate a PDF from an HTML element or string using.
+ *
+ * @param {Element|string} source The source element or HTML string.
+ * @param {Object=} options An object of optional settings.
+ */
+ jsPDFAPI.html = function (src, options) {
+ 'use strict';
+
+ options = options || {};
+ options.callback = options.callback || function () {};
+ options.html2canvas = options.html2canvas || {};
+ options.html2canvas.canvas = options.html2canvas.canvas || this.canvas;
+ options.html2canvas.windowHeight = options.html2canvas.windowHeight || Math.max(document.body.scrollHeight, document.body.offsetHeight, src.clientHeight, src.scrollHeight, src.offsetHeight);
+ options.jsPDF = options.jsPDF || this;
+ // Create a new worker with the given options.
+ var worker = new Worker(options);
+
+ if (!options.worker) {
+ // If worker is not set to true, perform the traditional 'simple' operation.
+ return worker.from(src).doCallback();
+ } else {
+ // Otherwise, return the worker for new Promise-based operation.
+ return worker;
+ }
+ return this;
+ };
+})(jsPDF.API, (typeof window !== "undefined" && window || typeof global !== "undefined" && global));
From ab86ef2df46675e1bd823142b1a10d474dd7b620 Mon Sep 17 00:00:00 2001
From: Aras Abbasi
Date: Sat, 8 Sep 2018 04:46:29 +0430
Subject: [PATCH 08/13] Add files via upload
---
examples/html2pdf/acid.html | 12 ++----------
examples/html2pdf/acid2.html | 13 ++++---------
examples/html2pdf/auto_break.html | 17 +++--------------
examples/html2pdf/lists.html | 17 +++++++----------
examples/html2pdf/page_break.html | 9 +++------
examples/html2pdf/pdf2.html | 12 +++---------
examples/html2pdf/showcase.html | 14 +++-----------
examples/html2pdf/showcase_supported_html.html | 8 +++-----
examples/html2pdf/tables.html | 15 +++------------
examples/html2pdf/total_mess.html | 11 +++--------
10 files changed, 34 insertions(+), 94 deletions(-)
diff --git a/examples/html2pdf/acid.html b/examples/html2pdf/acid.html
index 1b5a12f7d..c9698199f 100644
--- a/examples/html2pdf/acid.html
+++ b/examples/html2pdf/acid.html
@@ -157,20 +157,12 @@ sing to me, erbarme dich
-
+
Autobreak
The context2d plugin was tweaked to auto-break a document into multiple pages.
The auto-page-break feature allows vertical positioning by addressing the Y coordinate beyond the PDF page.
@@ -147,24 +147,13 @@
Autobreak