From 00e8d9254f7ee4c0accaf1e12860935dbb4fb3a0 Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 23 Mar 2016 00:05:23 +0100 Subject: [PATCH 1/5] Replace build.sh with node build script --- build.js | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 build.js diff --git a/build.js b/build.js new file mode 100644 index 000000000..0891d6368 --- /dev/null +++ b/build.js @@ -0,0 +1,82 @@ +var fs = require('fs'); +var uglify = require('uglify-js'); +var execSync = require('child_process').execSync; + +var paths = { + adler: 'node_modules/adler32cs/adler32cs.js', + fileSaver: 'node_modules/filesaver.js/FileSaver.js', + adlerTmp: 'adler.tmp.js', + fileSaverTmp: 'filesaver.tmp.js', + minified: 'dist/jspdf.min.js', + debug: 'dist/jspdf.debug.js' +}; + +var libs = [ + 'node_modules/cf-blob.js/Blob.js', + paths.fileSaverTmp, + paths.adlerTmp, + 'libs/css_colors.js', + 'libs/deflate.js', + 'libs/html2canvas/dist/html2canvas.js', + 'libs/png_support/png.js', + 'libs/png_support/zlib.js', + 'libs/polyfill.js' +]; +var files = execSync('find plugins/*.js').toString().trim().split(/\n/); +files.unshift('jspdf.js'); + +monkeyPatch(); +bundle(); + +fs.unlink(paths.adlerTmp); +fs.unlink(paths.fileSaverTmp); + +// Monkey patching adler32 and filesaver +function monkeyPatch() { + var adler = fs.readFileSync(paths.adler).toString(); + adler = adler.replace(/this, function/g, 'jsPDF, function'); + adler = adler.replace(/typeof define/g, '0'); + fs.writeFileSync(paths.adlerTmp, adler); + + var fileSaverCode = fs.readFileSync(paths.fileSaver).toString(); + fileSaverCode = fileSaverCode.replace(/define !== null\) && \(define.amd != null/g, '0'); + fs.writeFileSync(paths.fileSaverTmp, fileSaverCode); +} + +function bundle() { + var debug = execSync('cat ' + files.join(' ') + ' ' + libs.join(' ')).toString().trim(); + fs.writeFileSync(paths.debug, renew(debug)); + + var licences = extractLicences(); + var minifed = uglify.minify(files.concat(libs), {wrap: 'jspdf-exports'}); + fs.writeFileSync(paths.minified, renew('' + licences + minifed.code)); +} + +function renew(code) { + var date = new Date().toISOString(); + var version = require('./package.json').version; + var whoami = execSync('whoami').toString().trim(); + var commit = execSync('git rev-parse --short=10 HEAD').toString().trim(); + + code = code.replace('${versionID}', version + ' Built on ' + date); + code = code.replace('${commitID}', commit); + code = code.replace(/1\.0\.0-trunk/, version + ' ' + date + ':' + whoami); + + return code; +} + +function extractLicences() { + var licences = ''; + + files.concat(libs).forEach(function(file) { + var commentFilter = " | sed -n -e '1,/\\*\\//p' | sed -e 's/\\s*@preserve/ /' | grep -v *global"; + if (file !== 'jspdf.js') { + commentFilter += " | sed -e '/Permission/,/SOFTWARE\\./c \\'"; + } + + var lic = execSync("awk '/^\\/\\*/,/\\*\\//' " + file + commentFilter).toString(); + licences += lic.replace(/^\s*\n/gm, ''); + }); + + return licences; +} \ No newline at end of file diff --git a/package.json b/package.json index 5a3ea4e93..752655bf1 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "scripts": { "start": "ws", - "build": "npm install && bower install && ./build.sh", + "build": "npm install && bower install && node build.js", "version": "npm run build && git add -A dist" } } From 804785384e04e6aed9e9162de3a88bf8bc4ada01 Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 23 Mar 2016 00:07:16 +0100 Subject: [PATCH 2/5] Use rollupjs for bundling jspdf, plugins and libs --- build.js | 119 +++++++++++++++++++++++++++------------------------ libs/main.js | 29 +++++++++++++ package.json | 8 ++-- 3 files changed, 98 insertions(+), 58 deletions(-) create mode 100644 libs/main.js diff --git a/build.js b/build.js index 0891d6368..464949b85 100644 --- a/build.js +++ b/build.js @@ -1,55 +1,80 @@ var fs = require('fs'); +var rollup = require('rollup'); var uglify = require('uglify-js'); var execSync = require('child_process').execSync; -var paths = { - adler: 'node_modules/adler32cs/adler32cs.js', - fileSaver: 'node_modules/filesaver.js/FileSaver.js', - adlerTmp: 'adler.tmp.js', - fileSaverTmp: 'filesaver.tmp.js', +bundle({ minified: 'dist/jspdf.min.js', debug: 'dist/jspdf.debug.js' -}; - -var libs = [ - 'node_modules/cf-blob.js/Blob.js', - paths.fileSaverTmp, - paths.adlerTmp, - 'libs/css_colors.js', - 'libs/deflate.js', - 'libs/html2canvas/dist/html2canvas.js', - 'libs/png_support/png.js', - 'libs/png_support/zlib.js', - 'libs/polyfill.js' -]; -var files = execSync('find plugins/*.js').toString().trim().split(/\n/); -files.unshift('jspdf.js'); - -monkeyPatch(); -bundle(); - -fs.unlink(paths.adlerTmp); -fs.unlink(paths.fileSaverTmp); +}); // Monkey patching adler32 and filesaver function monkeyPatch() { - var adler = fs.readFileSync(paths.adler).toString(); - adler = adler.replace(/this, function/g, 'jsPDF, function'); - adler = adler.replace(/typeof define/g, '0'); - fs.writeFileSync(paths.adlerTmp, adler); + return { + transform: function (code, id) { + var file = id.split('/').pop(); + if (file === 'adler32cs.js') { + code = code.replace(/this, function/g, 'jsPDF, function'); + code = code.replace(/typeof define/g, '0'); + } else if (file === 'FileSaver.js') { + code = code.replace(/define !== null\) && \(define.amd != null/g, '0'); + } + return code; + } + } +} + +// Rollup removes local variables unless used within a module. +// This plugin makes sure specified local variables are preserved +// and kept local. This plugin won't be necessary once es2015 +// modules are used. +function rawjs(opts) { + opts = opts || {}; + return { + transform: function (code, id) { + var variable = opts[id.split('/').pop()]; + if (!variable) return code; - var fileSaverCode = fs.readFileSync(paths.fileSaver).toString(); - fileSaverCode = fileSaverCode.replace(/define !== null\) && \(define.amd != null/g, '0'); - fs.writeFileSync(paths.fileSaverTmp, fileSaverCode); + var keepStr = '/*rollup-keeper-start*/window.tmp=' + variable + ';/*rollup-keeper-end*/'; + return code + keepStr; + }, + transformBundle: function (code) { + for (var file in opts) { + var r = new RegExp(opts[file] + '\\$\\d+', 'g'); + code = code.replace(r, opts[file]); + } + var re = /\/\*rollup-keeper-start\*\/.*\/\*rollup-keeper-end\*\//g; + return code.replace(re, ''); + } + } } -function bundle() { - var debug = execSync('cat ' + files.join(' ') + ' ' + libs.join(' ')).toString().trim(); - fs.writeFileSync(paths.debug, renew(debug)); +function bundle(paths) { + rollup.rollup({ + entry: './libs/main.js', + plugins: [ + monkeyPatch(), + rawjs({ + 'jspdf.js': 'jsPDF', + 'filesaver.tmp.js': 'saveAs', + 'deflate.js': 'Deflater', + 'zlib.js': 'FlateStream', + 'css_colors.js': 'CssColors', + 'html2pdf.js': 'html2pdf' + }) + ] + }).then(function (bundle) { + var code = bundle.generate({format: 'umd'}).code; + code = code.replace(/'use strict';/, ''); + code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./, 'Licensed under the MIT License'); + code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./g, ''); + fs.writeFileSync(paths.debug, renew(code)); - var licences = extractLicences(); - var minifed = uglify.minify(files.concat(libs), {wrap: 'jspdf-exports'}); - fs.writeFileSync(paths.minified, renew('' + licences + minifed.code)); + var minified = uglify.minify(code, {fromString: true, output: {comments: /@preserve|@license|copyright/i}}); + fs.writeFileSync(paths.minified, renew(minified.code)); + }).catch(function (err) { + console.error(err); + }); } function renew(code) { @@ -63,20 +88,4 @@ function renew(code) { code = code.replace(/1\.0\.0-trunk/, version + ' ' + date + ':' + whoami); return code; -} - -function extractLicences() { - var licences = ''; - - files.concat(libs).forEach(function(file) { - var commentFilter = " | sed -n -e '1,/\\*\\//p' | sed -e 's/\\s*@preserve/ /' | grep -v *global"; - if (file !== 'jspdf.js') { - commentFilter += " | sed -e '/Permission/,/SOFTWARE\\./c \\'"; - } - - var lic = execSync("awk '/^\\/\\*/,/\\*\\//' " + file + commentFilter).toString(); - licences += lic.replace(/^\s*\n/gm, ''); - }); - - return licences; } \ No newline at end of file diff --git a/libs/main.js b/libs/main.js new file mode 100644 index 000000000..b60d720da --- /dev/null +++ b/libs/main.js @@ -0,0 +1,29 @@ +import '../jspdf'; + +import '../plugins/acroform'; +import '../plugins/addhtml'; +import '../plugins/addimage'; +import '../plugins/annotations'; +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'; +import '../plugins/prevent_scale_to_fit'; +import '../plugins/split_text_to_size'; +import '../plugins/standard_fonts_metrics'; +import '../plugins/svg'; +import '../plugins/total_pages'; + +import '../node_modules/cf-blob.js/Blob.js'; +import '../node_modules/filesaver.js/FileSaver.js'; +import '../node_modules/adler32cs/adler32cs.js'; +import './css_colors.js'; +import './deflate.js'; +import './html2canvas/dist/html2canvas.js'; +import './png_support/png.js'; +import './png_support/zlib.js'; +import './polyfill.js'; \ No newline at end of file diff --git a/package.json b/package.json index 752655bf1..8d024bc80 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,14 @@ "type": "git", "url": "https://github.com/MrRio/jsPDF.git" }, - "dependencies": {}, - "devDependencies": { + "dependencies": { "adler32cs": "github:chick307/adler32cs.js", "cf-blob.js": "0.0.1", - "filesaver.js": "github:andyinabox/FileSaver.js", + "filesaver.js": "github:andyinabox/FileSaver.js" + }, + "devDependencies": { "local-web-server": "^0.5.19", + "rollup": "^0.25.4", "uglify-js": "^2.6.2" }, "scripts": { From 1325e61174eb7a311535ed8017f539e830ed92d3 Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 23 Mar 2016 00:07:34 +0100 Subject: [PATCH 3/5] Enable strict mode for entire library --- build.js | 1 - plugins/acroform.js | 25 ++++++++++++++++--------- plugins/from_html.js | 3 ++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/build.js b/build.js index 464949b85..a674eabec 100644 --- a/build.js +++ b/build.js @@ -65,7 +65,6 @@ function bundle(paths) { ] }).then(function (bundle) { var code = bundle.generate({format: 'umd'}).code; - code = code.replace(/'use strict';/, ''); code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./, 'Licensed under the MIT License'); code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./g, ''); fs.writeFileSync(paths.debug, renew(code)); diff --git a/plugins/acroform.js b/plugins/acroform.js index 9d8fe8156..ee85c1298 100644 --- a/plugins/acroform.js +++ b/plugins/acroform.js @@ -6,8 +6,10 @@ * http://opensource.org/licenses/mit-license */ -(AcroForm = function (jsPDFAPI) { +(window.AcroForm = function (jsPDFAPI) { 'use strict'; + + var AcroForm = window.AcroForm; AcroForm.scale = function (x) { return (x * (acroformPlugin.internal.scaleFactor / 1));// 1 = (96 / 72) @@ -217,10 +219,10 @@ var key = i; var form = fieldArray[i]; // Start Writing the Object - this.internal.newObjectDeferredBegin(form.objId); + this.internal.newObjectDeferredBegin(form && form.objId); var content = ""; - content += (form.getString()); + content += form ? form.getString() : ''; this.internal.out(content); delete fieldArray[key]; @@ -402,6 +404,8 @@ }; })(jsPDF.API); +var AcroForm = window.AcroForm; + AcroForm.internal = {}; AcroForm.createFormXObject = function (formObject) { @@ -757,10 +761,10 @@ AcroForm.internal.toPdfString = function (string) { string = string || ""; // put Bracket at the Beginning of the String - if (String.indexOf('(', 0) !== 0) { + if (string.indexOf('(') !== 0) { string = '(' + string; } - + if (string.substring(string.length - 1) != ')') { string += '('; } @@ -1043,7 +1047,8 @@ AcroForm.Field = function () { Object.defineProperty(this, 'hasAppearanceStream', { enumerable: false, - configurable: true + configurable: true, + writable: true }); }; AcroForm.Field.FieldNum = 0; @@ -1088,9 +1093,11 @@ AcroForm.ChoiceField = function () { configurable: false }); this.hasAppearanceStream = true; - this.V.get = function () { - AcroForm.internal.toPdfString(); - }; + Object.defineProperty(this, 'V', { + get: function() { + AcroForm.internal.toPdfString(); + } + }); }; AcroForm.internal.inherit(AcroForm.ChoiceField, AcroForm.Field); window["ChoiceField"] = AcroForm.ChoiceField; diff --git a/plugins/from_html.js b/plugins/from_html.js index ec9b447eb..1bdccc261 100644 --- a/plugins/from_html.js +++ b/plugins/from_html.js @@ -33,6 +33,7 @@ DrillForContent, FontNameDB, FontStyleMap, + TextAlignMap, FontWeightMap, FloatMap, ClearMap, @@ -943,7 +944,7 @@ } //if we have to move the cursor to adapt the indent var indentMove = 0; - var indentMore = 0; + var wantedIndent = 0; //if a margin was added (by e.g. a text-alignment), move the cursor if (line[0][1]["margin-left"] !== undefined && line[0][1]["margin-left"] > 0) { wantedIndent = this.pdf.internal.getCoordinateString(line[0][1]["margin-left"]); From 2cec2716d3fa4cc3b5e293670091988cb51eba02 Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 23 Mar 2016 11:23:59 +0100 Subject: [PATCH 4/5] Proper output of umd (support for browserify, webpack, requirejs etc) --- build.js | 10 ++++------ libs/main.js | 4 +++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.js b/build.js index a674eabec..d97afbd98 100644 --- a/build.js +++ b/build.js @@ -15,9 +15,7 @@ function monkeyPatch() { var file = id.split('/').pop(); if (file === 'adler32cs.js') { code = code.replace(/this, function/g, 'jsPDF, function'); - code = code.replace(/typeof define/g, '0'); - } else if (file === 'FileSaver.js') { - code = code.replace(/define !== null\) && \(define.amd != null/g, '0'); + code = code.replace(/require\('buffer'\)/g, '{}'); } return code; } @@ -26,8 +24,8 @@ function monkeyPatch() { // Rollup removes local variables unless used within a module. // This plugin makes sure specified local variables are preserved -// and kept local. This plugin won't be necessary once es2015 -// modules are used. +// and kept local. This plugin wouldn't be necessary if es2015 +// modules would be used. function rawjs(opts) { opts = opts || {}; return { @@ -64,7 +62,7 @@ function bundle(paths) { }) ] }).then(function (bundle) { - var code = bundle.generate({format: 'umd'}).code; + var code = bundle.generate({format: 'umd', moduleName: 'jspdf'}).code; code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./, 'Licensed under the MIT License'); code = code.replace(/Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./g, ''); fs.writeFileSync(paths.debug, renew(code)); diff --git a/libs/main.js b/libs/main.js index b60d720da..ce4a90b34 100644 --- a/libs/main.js +++ b/libs/main.js @@ -26,4 +26,6 @@ import './deflate.js'; import './html2canvas/dist/html2canvas.js'; import './png_support/png.js'; import './png_support/zlib.js'; -import './polyfill.js'; \ No newline at end of file +import './polyfill.js'; + +export default jsPDF; \ No newline at end of file From c3dc3914dae5a2a86da878ce063d2cf059df7e9a Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 23 Mar 2016 11:29:36 +0100 Subject: [PATCH 5/5] Transpile jspdf and plugins with babeljs --- build.js | 7 ++++++- libs/main.js | 31 ------------------------------- main.js | 31 +++++++++++++++++++++++++++++++ package.json | 2 ++ 4 files changed, 39 insertions(+), 32 deletions(-) delete mode 100644 libs/main.js create mode 100644 main.js diff --git a/build.js b/build.js index d97afbd98..a691e9ba3 100644 --- a/build.js +++ b/build.js @@ -1,6 +1,7 @@ var fs = require('fs'); var rollup = require('rollup'); var uglify = require('uglify-js'); +var babel = require('rollup-plugin-babel'); var execSync = require('child_process').execSync; bundle({ @@ -49,7 +50,7 @@ function rawjs(opts) { function bundle(paths) { rollup.rollup({ - entry: './libs/main.js', + entry: './main.js', plugins: [ monkeyPatch(), rawjs({ @@ -59,6 +60,10 @@ function bundle(paths) { 'zlib.js': 'FlateStream', 'css_colors.js': 'CssColors', 'html2pdf.js': 'html2pdf' + }), + babel({ + presets: ['es2015-rollup'], + exclude: ['node_modules/**', 'libs/**'] }) ] }).then(function (bundle) { diff --git a/libs/main.js b/libs/main.js deleted file mode 100644 index ce4a90b34..000000000 --- a/libs/main.js +++ /dev/null @@ -1,31 +0,0 @@ -import '../jspdf'; - -import '../plugins/acroform'; -import '../plugins/addhtml'; -import '../plugins/addimage'; -import '../plugins/annotations'; -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'; -import '../plugins/prevent_scale_to_fit'; -import '../plugins/split_text_to_size'; -import '../plugins/standard_fonts_metrics'; -import '../plugins/svg'; -import '../plugins/total_pages'; - -import '../node_modules/cf-blob.js/Blob.js'; -import '../node_modules/filesaver.js/FileSaver.js'; -import '../node_modules/adler32cs/adler32cs.js'; -import './css_colors.js'; -import './deflate.js'; -import './html2canvas/dist/html2canvas.js'; -import './png_support/png.js'; -import './png_support/zlib.js'; -import './polyfill.js'; - -export default jsPDF; \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 000000000..994746f65 --- /dev/null +++ b/main.js @@ -0,0 +1,31 @@ +import './jspdf'; + +import './plugins/acroform'; +import './plugins/addhtml'; +import './plugins/addimage'; +import './plugins/annotations'; +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'; +import './plugins/prevent_scale_to_fit'; +import './plugins/split_text_to_size'; +import './plugins/standard_fonts_metrics'; +import './plugins/svg'; +import './plugins/total_pages'; + +import './node_modules/cf-blob.js/Blob.js'; +import './node_modules/filesaver.js/FileSaver.js'; +import './node_modules/adler32cs/adler32cs.js'; +import './libs/css_colors.js'; +import './libs/deflate.js'; +import './libs/html2canvas/dist/html2canvas.js'; +import './libs/png_support/png.js'; +import './libs/png_support/zlib.js'; +import './libs/polyfill.js'; + +export default jsPDF; \ No newline at end of file diff --git a/package.json b/package.json index 8d024bc80..935360c5c 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,10 @@ "filesaver.js": "github:andyinabox/FileSaver.js" }, "devDependencies": { + "babel-preset-es2015-rollup": "^1.1.1", "local-web-server": "^0.5.19", "rollup": "^0.25.4", + "rollup-plugin-babel": "^2.4.0", "uglify-js": "^2.6.2" }, "scripts": {