diff --git a/jspdf/jspdf-tests.ts b/jspdf/jspdf-tests.ts
new file mode 100644
index 0000000000..385eb7fc4a
--- /dev/null
+++ b/jspdf/jspdf-tests.ts
@@ -0,0 +1,238 @@
+///
+
+// From: https://mrrio.github.io/jsPDF/examples/basic.html
+
+function test_simple_two_page_document() {
+ var doc = new jsPDF();
+ doc.text(20, 20, 'Hello world!');
+ doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
+ doc.addPage();
+ doc.text(20, 20, 'Do you like that?');
+ doc.save('Test.pdf');
+}
+
+function test_landscape() {
+ var doc = new jsPDF('landscape');
+ doc.text(20, 20, 'Hello landscape world!');
+ doc.save('Test.pdf');
+}
+
+function test_metadata() {
+ var doc = new jsPDF();
+ doc.text(20, 20, 'This PDF has a title, subject, author, keywords and a creator.');
+ doc.setProperties({
+ title: 'Title',
+ subject: 'This is the subject',
+ author: 'James Hall',
+ keywords: 'generated, javascript, web 2.0, ajax',
+ creator: 'MEEE'
+ });
+ doc.save('Test.pdf');
+}
+
+function test_user_input() {
+ var doc = new jsPDF();
+ doc.text(20, 20, 'This PDF has a title, subject, author, keywords and a creator.');
+ doc.setProperties({
+ title: 'Title',
+ subject: 'This is the subject',
+ author: 'James Hall',
+ keywords: 'generated, javascript, web 2.0, ajax',
+ creator: 'MEEE'
+ });
+ doc.save('Test.pdf');
+}
+
+function test_font_sizes() {
+ var doc = new jsPDF();
+ doc.setFontSize(22);
+ doc.text(20, 20, 'This is a title');
+ doc.setFontSize(16);
+ doc.text(20, 30, 'This is some normal sized text underneath.');
+ doc.save('Test.pdf');
+}
+
+function test_font_types() {
+ var doc = new jsPDF();
+ doc.text(20, 20, 'This is the default font.');
+ doc.setFont("courier");
+ doc.text(20, 30, 'This is courier normal.');
+ doc.setFont("times");
+ doc.setFontType("italic");
+ doc.text(20, 40, 'This is times italic.');
+ doc.setFont("helvetica");
+ doc.setFontType("bold");
+ doc.text(20, 50, 'This is helvetica bold.');
+ doc.setFont("courier");
+ doc.setFontType("bolditalic");
+ doc.text(20, 60, 'This is courier bolditalic.');
+ doc.save('Test.pdf');
+}
+
+function test_text_colors() {
+ var doc = new jsPDF();
+ doc.setTextColor(100);
+ doc.text(20, 20, 'This is gray.');
+ doc.setTextColor(150);
+ doc.text(20, 30, 'This is light gray.');
+ doc.setTextColor(255, 0, 0);
+ doc.text(20, 40, 'This is red.');
+ doc.setTextColor(0, 255, 0);
+ doc.text(20, 50, 'This is green.');
+ doc.setTextColor(0, 0, 255);
+ doc.text(20, 60, 'This is blue.');
+ doc.save('Test.pdf');
+}
+
+function test_font_metrics_based_line_sizing_split() {
+ var pdf = new jsPDF('p', 'in', 'letter');
+ var sizes:number[] = [12, 16, 20];
+ var fonts = [['Times', 'Roman'], ['Helvetica', ''], ['Times', 'Italic']];
+ var font:string[];
+ var size:number;
+ var lines:any[];
+ var verticalOffset = 0.5; // inches on a 8.5 x 11 inch sheet.
+ var loremipsum = 'Lorem ipsum dolor sit amet, ...';
+ for (var i in fonts) {
+ if (fonts.hasOwnProperty(i)) {
+ font = fonts[i];
+ size = sizes[i];
+ lines = pdf.setFont(font[0], font[1])
+ .setFontSize(size)
+ .splitTextToSize(loremipsum, 7.5);
+ pdf.text(0.5, verticalOffset + size / 72, lines);
+ verticalOffset += (lines.length + 0.5) * size / 72
+ }
+ }
+ pdf.save('Test.pdf');
+}
+
+function test_from_html() {
+ var pdf = new jsPDF('p', 'pt', 'letter')
+ , source = document.getElementById('#fromHTMLtestdiv')
+ , specialElementHandlers = {
+ '#bypassme': function (element:HTMLElement, renderer:any) {
+ return true
+ }
+ };
+ var margins = {
+ top: 80,
+ bottom: 60,
+ left: 40,
+ width: 522
+ };
+
+ pdf.fromHTML(
+ source // HTML string or DOM elem ref.
+ , margins.left // x coord
+ , margins.top // y coord
+ , {
+ 'width': margins.width // max width of content on PDF
+ , 'elementHandlers': specialElementHandlers
+ },
+ function (dispose:any) {
+ pdf.save('Test.pdf');
+ },
+ margins
+ )
+}
+
+function test_rect_squares() {
+ var doc = new jsPDF();
+ doc.rect(20, 20, 10, 10); // empty square
+ doc.rect(40, 20, 10, 10, 'F'); // filled square
+ doc.setDrawColor(255, 0, 0);
+ doc.rect(60, 20, 10, 10); // empty red square
+ doc.setDrawColor(255, 0, 0);
+ doc.rect(80, 20, 10, 10, 'FD'); // filled square with red borders
+ doc.setDrawColor(0);
+ doc.setFillColor(255, 0, 0);
+ doc.rect(100, 20, 10, 10, 'F'); // filled red square
+ doc.setDrawColor(0);
+ doc.setFillColor(255, 0, 0);
+ doc.rect(120, 20, 10, 10, 'FD'); // filled red square with black borders
+ doc.setDrawColor(0);
+ doc.setFillColor(255, 255, 255);
+ doc.roundedRect(140, 20, 10, 10, 3, 3, 'FD'); // Black sqaure with rounded corners
+ doc.save('Test.pdf');
+}
+
+function test_lines() {
+ var doc = new jsPDF();
+ doc.line(20, 20, 60, 20); // horizontal line
+ doc.setLineWidth(0.5);
+ doc.line(20, 25, 60, 25);
+ doc.setLineWidth(1);
+ doc.line(20, 30, 60, 30);
+ doc.setLineWidth(1.5);
+ doc.line(20, 35, 60, 35);
+ doc.setDrawColor(255, 0, 0); // draw red lines
+ doc.setLineWidth(0.1);
+ doc.line(100, 20, 100, 60); // vertical line
+ doc.setLineWidth(0.5);
+ doc.line(105, 20, 105, 60);
+ doc.setLineWidth(1);
+ doc.line(110, 20, 110, 60);
+ doc.setLineWidth(1.5);
+ doc.line(115, 20, 115, 60);
+ doc.save('Test.pdf');
+}
+
+function test_circles_ellipses() {
+ var doc = new jsPDF();
+ doc.ellipse(40, 20, 10, 5);
+ doc.setFillColor(0, 0, 255);
+ doc.ellipse(80, 20, 10, 5, 'F');
+ doc.setLineWidth(1);
+ doc.setDrawColor(0);
+ doc.setFillColor(255, 0, 0);
+ doc.circle(120, 20, 5, 'FD');
+ doc.save('Test.pdf');
+}
+
+function test_triangles() {
+ var doc = new jsPDF();
+ doc.triangle(60, 100, 60, 120, 80, 110, 'FD');
+ doc.setLineWidth(1);
+ doc.setDrawColor(255, 0, 0);
+ doc.setFillColor(0, 0, 255);
+ doc.triangle(100, 100, 110, 100, 120, 130, 'FD');
+ doc.save('My file.pdf');
+}
+
+function test_images() {
+ var getImageFromUrl = function (url:string, callback:Function) {
+ var img = new Image();
+ img.onerror = function () {
+ alert('Cannot load image: "' + url + '"');
+ };
+ img.onload = function () {
+ callback(img);
+ };
+ img.src = url;
+ };
+
+ var createPDF = function (imgData:string) {
+ var doc = new jsPDF();
+ doc.addImage(imgData, 'JPEG', 10, 10, 50, 50, 'monkey'); // Cache the image using the alias 'monkey'
+ doc.addImage('monkey', 70, 10, 100, 120); // use the cached 'monkey' image, JPEG is optional regardless
+ doc.addImage({
+ imageData: imgData,
+ angle: -20,
+ x: 10,
+ y: 78,
+ w: 45,
+ h: 58
+ });
+ doc.output('datauri');
+ };
+ getImageFromUrl('thinking-monkey.jpg', createPDF);
+}
+
+function test_add_html() {
+ var pdf = new jsPDF('p', 'pt', 'a4');
+ pdf.addHTML(document.body, function () {
+ var string = pdf.output('datauristring');
+ document.getElementsByClassName('preview-pane')[0].setAttribute('src', string);
+ });
+}
diff --git a/jspdf/jspdf.d.ts b/jspdf/jspdf.d.ts
new file mode 100644
index 0000000000..465a9207ae
--- /dev/null
+++ b/jspdf/jspdf.d.ts
@@ -0,0 +1,203 @@
+// Type definitions for jsPDF v1.1.135
+// Project: https://github.com/MrRio/jsPDF
+// Definitions by: Amber Schühmacher
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+declare class jsPDF {
+ constructor(orientation?:any,
+ unit?:string,
+ format?:string,
+ compressPdf?:number);
+
+ CapJoinStyles:any;
+ version:string;
+
+ internal: {
+ 'pdfEscape'(text:string, flags:any): any;
+ 'getStyle'(style:string) : any;
+ 'getFont'(): any;
+ 'getFontSize'():number;
+ 'getLineHeight'():number;
+ 'write'(string1:string):any;
+ 'getCoordinateString'(value:number):number;
+ 'getVerticalCoordinateString'(value:number):number;
+ 'collections':any;
+ 'newObject'():number;
+ 'newAdditionalObject'():any;
+ 'newObjectDeferred'():number;
+ 'newObjectDeferredBegin'(oid:number):void;
+ 'putStream'(str:string):void;
+ 'events':any;
+ 'scaleFactor':number;
+ 'pageSize': {
+ width:number;
+ height:number;
+ };
+ 'output'(type:any, options:any):any;
+ 'getNumberOfPages'():number;
+ 'pages':number[];
+ 'out'(string:string):void;
+ 'f2'(number:number):number;
+ 'getPageInfo'(pageNumberOneBased:number):any;
+ 'getCurrentPageInfo'():any;
+ };
+ addPage():jsPDF;
+ setPage(n:number):jsPDF;
+ insertPage(beforePage:number):jsPDF;
+ movePage(targetPage:number, beforePage:number):jsPDF;
+ deletePage(n:number):jsPDF;
+ setDisplayMode(zoom?:string, layout?:string, pmode?:string):jsPDF;
+ text(text:any, x:any, y:any, flags?:any, angle?:any, align?:any):jsPDF;
+ lstext(text:string, x:number, y:number, spacing:number):jsPDF;
+ line(x1:number, y1:number, x2:number, y2:number):any;
+ clip():void;
+ lines(lines:any, x:any, y:any, scale?:any, style?:string, closed?:boolean):jsPDF;
+ rect(x:number, y:number, w:number, h:number, style?:string):jsPDF;
+ triangle(x1:number, y1:number, x2:number, y2:number, x3:number, y3:number, style:string):jsPDF;
+ roundedRect(x:number, y:number, w:number, h:number, rx:number, ry:number, style:string):jsPDF;
+ ellipse(x:number, y:number, rx:number, ry:number, style?:string):jsPDF;
+ circle(x:number, y:number, r:number, style:string):jsPDF;
+ setProperties(properties:any):jsPDF;
+ setFontSize(size:number):jsPDF;
+ setFont(fontName?:string, fontStyle?:string):jsPDF;
+ setFontStyle(style:string):jsPDF;
+ setFontType(style:string):jsPDF;
+ getFontList():any;
+ addFont(postScriptName:string, fontName:string, fontStyle:string):string;
+ setLineWidth(width:number):jsPDF;
+ setDrawColor(ch1:number|string, ch2?:number, ch3?:number, ch4?:number):jsPDF;
+ setFillColor(ch1:number|string, ch2?:number, ch3?:number, ch4?:number):jsPDF;
+ setTextColor(r?:number, g?:number, b?:number):jsPDF;
+ setLineCap(style:string|number):jsPDF;
+ setLineJoin(style:string|number):jsPDF;
+ output(type?:string, options?:any):any;
+ save(filename:string):jsPDF;
+
+ /**
+ * jsPDF plugins below:
+ *
+ * - AddHTML
+ * - AddImage
+ * - Annotations
+ * - AutoPrint
+ * - Canvas
+ * - Cell
+ * - Context2D
+ * - FromHTML
+ * - JavaScript
+ * - PNG
+ * - split_text_to_size
+ * - SVG
+ * - total_pages
+ */
+
+ // jsPDF plugin: addHTML
+ addHTML(element:any, x:number, y:number, options:any, callback:Function):jsPDF;
+ addHTML(element:any, callback:Function):jsPDF;
+
+ // jsPDF plugin: addImage
+ color_spaces:any;
+ decode:any;
+ image_compression:any;
+
+ sHashCode(str:string):any;
+ isString(object:any):boolean;
+ extractInfoFromBase64DataURI(dataURI:string):any[];
+ supportsArrayBuffer():boolean;
+ isArrayBuffer(object:any):boolean;
+ isArrayBufferView(object:any):boolean;
+ binaryStringToUint8Array(binary_string:string):Uint8Array;
+ arrayBufferToBinaryString(buffer:any):string;
+ arrayBufferToBase64(arrayBuffer:ArrayBuffer):string;
+ createImageInfo(data:any, wd:any, ht:any, cs:any, bpc:any, imageIndex:number, alias:any, f?:any, dp?:any, trns?:any, pal?:any, smask?:any):any;
+ addImage(imageData?:any, format?:any, x?:number, y?:number, w?:number, h?:number, alias?:any, compression?:any, rotation?:any):jsPDF;
+ processJPEG(data:any, index:number, alias:any, compression?:any, dataAsBinaryString?:string):any;
+ processJPG():any;
+
+ // jsPDF plugin: Annotations
+ annotationPlugin:any;
+ createAnnotation(options:any):void;
+ link(x:number, y:number, w:number, h:number, options:any):void;
+ textWithLink(text:string, x:number, y:number, options:any):number;
+ getTextWidth(text:string):number;
+ getLineHeight():number;
+
+ // jsPDF plugin: AutoPrint
+ autoPrint():jsPDF;
+
+ // jsPDF plugin: Canvas
+ canvas: {
+ getContext():any;
+ style:any;
+ };
+
+ // jsPDF plugin: Cell
+ setHeaderFunction(func:Function):void;
+ getTextDimensions(txt:string):any;
+ cellAddPage():void;
+ cellInitialize():void;
+ cell(x:number, y:number, w:number, h:number, txt:string, ln:number, align:string):jsPDF;
+ arrayMax(array:any[], comparisonFn?:Function):number;
+ table(x:number, y:number, data:any, headers:string[], config:any):jsPDF;
+ calculateLineHeight(headerNames:string[], columnWidths:number[], model:any[]):number;
+ setTableHeaderRow(config:any[]):void;
+ printHeaderRow(lineNumber:number, new_page?:boolean):void;
+
+ // jsPDF plugin: Context2D
+ context2d: {
+ pageWrapXEnabled: boolean;
+ pageWrapYEnabled: boolean;
+ pageWrapX: number;
+ pageWrapY: number;
+ f2(number:number):number;
+ fillRect(x:number, y:number, w:number, h:number):void;
+ strokeRect(x:number, y:number, w:number, h:number):void;
+ clearRect(x:number, y:number, w:number, h:number):void;
+ save():void;
+ restore():void;
+ beginPath():void;
+ closePath():void;
+ setFillStyle(style:string):void;
+ setStrokeStyle(style:string):void;
+ fillText(text:string|string[], x:number, y:number, maxWidth:number):void;
+ strokeText(text:string|string[], x:number, y:number, maxWidth:number):void;
+ setFont(font:string):void;
+ setTextBaseline(baseline:string):void;
+ getTextBaseline():string;
+ setLineWidth(width:number):void;
+ setLineCap(style:string):void;
+ setLineJoin(style:string):void;
+ moveTo(x:number, y:number):void;
+ lastBreak: number;
+ pageBreaks: any[];
+ lineTo(x:number, y:number):void;
+ bezierCurveTo(x1:number, y1:number, x2:number, y2:number, x:number, y:number):void;
+ quadraticCurveTo(x1:number, y1:number, x:number, y:number):void;
+ arc(x:number, y:number, radius:number, startAngle:number, endAngle:number, anticlockwise:any):void;
+ drawImage(img:string, x:number, y:number, w:number, h:number, x2?:number, y2?:number, w2?:number, h2?:number):void;
+ stroke():void;
+ fill():void;
+ translate(x:number, y:number):void;
+ measureText(text:string):number;
+ };
+
+ // jsPDF plugin: fromHTML
+ fromHTML(HTML:string | HTMLElement, x:number, y:number, settings?:any, callback?:Function, margins?:any):jsPDF;
+
+ // jsPDF plugin: JavaScript
+ addJS(txt:string):jsPDF;
+
+ // jsPDF plugin: PNG
+ processPNG(imageData:any, imageIndex:number, alias:string, compression:any, dataAsBinaryString:string):any;
+
+ // jsPDF plugin: split_text_to_size
+ getCharWidthsArray(text:string, options?:any):any[];
+ getStringUnitWidth(text:string, options?:any):number;
+ splitTextToSize(text:string, maxlen:number, options?:any):any;
+
+ // jsPDF plugin: SVG
+ addSVG(svgtext:string, x:number, y:number, w?:number, h?:number):jsPDF;
+
+ // jsPDF plugin: total_pages
+ putTotalPages(pageExpression:string):jsPDF;
+}