diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..06f64d2 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,180 @@ +{ + "parserOptions": { + "ecmaVersion": 8, + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + }, + "sourceType": "module" + }, + + "env": { + "es6": true, + "node": true + }, + + "plugins": [ + ], + + "globals": { + "document": false, + "navigator": false, + "window": false, + "app": false, + "WebSocket": false, + "alert": false, + "d3": false, + "angular": false, + "CodeMirror": true, + "saveAs": true, + "Blob": true, + "marked": true, + "THREE": true + }, + + "rules": { + "accessor-pairs": "error", + "arrow-spacing": ["error", { "before": true, "after": true }], + "block-spacing": ["error", "always"], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": ["error", { "properties": "never" }], + "comma-dangle": ["error", { + "arrays": "never", + "objects": "never", + "imports": "never", + "exports": "never", + "functions": "never" + }], + "comma-spacing": ["error", { "before": false, "after": true }], + "comma-style": ["error", "last"], + "constructor-super": "error", + "curly": ["error", "multi-line"], + "dot-location": ["error", "property"], + "eol-last": "error", + "eqeqeq": ["error", "always", { "null": "ignore" }], + "func-call-spacing": ["error", "never"], + "generator-star-spacing": ["error", { "before": true, "after": true }], + "handle-callback-err": ["error", "^(err|error)$" ], + "indent": ["error", 3, { "SwitchCase": 1 }], + "key-spacing": ["error", { "beforeColon": false, "afterColon": true }], + "keyword-spacing": ["error", { "before": true, "after": true }], + "new-cap": ["error", { "newIsCap": false, "properties": false}], + "new-parens": "error", + "no-array-constructor": "error", + "no-caller": "error", + "no-class-assign": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": "error", + "no-const-assign": "error", + "no-constant-condition": ["error", { "checkLoops": false }], + "no-control-regex": "error", + "no-debugger": "error", + "no-delete-var": "error", + "no-dupe-args": "error", + "no-dupe-class-members": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty-character-class": "error", + "no-empty-pattern": "error", + "no-eval": "error", + "no-ex-assign": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-boolean-cast": "error", + "no-extra-parens": ["error", "functions"], + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-func-assign": "error", + "no-global-assign": "error", + "no-implied-eval": "error", + "no-inner-declarations": ["error", "functions"], + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": ["error", { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": "error", + "no-mixed-operators": ["error", { + "groups": [ + ["==", "!=", "===", "!==", ">", ">=", "<", "<="], + ["&&", "||"], + ["in", "instanceof"] + ], + "allowSamePrecedence": true + }], + "no-mixed-spaces-and-tabs": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 0 }], + "no-negated-in-lhs": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-require": "error", + "no-new-symbol": "error", + "no-new-wrappers": "error", + "no-obj-calls": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-path-concat": "error", + "no-proto": "error", + "no-redeclare": "error", + "no-regex-spaces": "error", + "no-return-assign": ["error", "except-parens"], + "no-return-await": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow-restricted-names": "error", + "no-sparse-arrays": "error", + "no-tabs": "error", + "no-template-curly-in-string": "error", + "no-this-before-super": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef": "error", + "no-undef-init": "error", + "no-unexpected-multiline": "error", + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": ["error", { "defaultAssignment": false }], + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }], + "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], + "no-use-before-define": ["error", { "functions": false, "classes": false, "variables": false }], + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-useless-escape": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }], + "operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" } }], + "prefer-promise-reject-errors": "error", + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], + "rest-spread-spacing": ["error", "never"], + "semi": ["error", "always"], + "semi-spacing": ["error", { "before": false, "after": true }], + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", "always"], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + "space-unary-ops": ["error", { "words": true, "nonwords": false }], + "spaced-comment": ["error", "always", { + "line": { "markers": ["*package", "!", "/", ",", "="] }, + "block": { "balanced": true, "markers": ["*package", "!", ",", ":", "::", "flow-include"], "exceptions": ["*"] } + }], + "symbol-description": "error", + "template-curly-spacing": ["error", "never"], + "template-tag-spacing": ["error", "never"], + "unicode-bom": ["error", "never"], + "use-isnan": "error", + "valid-typeof": ["error", { "requireStringLiterals": true }], + "wrap-iife": ["error", "any", { "functionPrototypeMethods": true }], + "yield-star-spacing": ["error", "both"], + "yoda": ["error", "never"], + } +} diff --git a/example.js b/example.js index f15c2b2..de3c174 100644 --- a/example.js +++ b/example.js @@ -1,22 +1,22 @@ var url2pdf = require('./index'); var q = require('q'); -console.log("Running example"); +console.log('Running example'); q.all([ - url2pdf.renderPdf("http://www.google.com", {paperSize: {orientation: "landscape"}}), - url2pdf.renderPdf("http://www.google.com"), + url2pdf.renderPdf('http://www.google.com', {paperSize: {orientation: 'landscape'}}), + url2pdf.renderPdf('http://www.google.com'), - url2pdf.renderFromHTML("
"),
- url2pdf.renderFromHTML("
", {loadTimeout: 2000})
- ])
- .then(function (paths) {
- console.log("Created PDFs @", paths);
- // manual clenup could be done here, but better use autocelan
- // if you want a manual cleanup, disable autoclean by setting option: autoCleanFileAgeInSec = -1
- // then do the cleanup manual; use a timeout to prevent deleting pending operations
- // console.log("Deleted", url2pdf.cleanup(5)); // remove all files older than 5 seconds
- })
- .catch(function (err) {
- console.error(err.stack);
- });
+ url2pdf.renderFromHTML("
"),
+ url2pdf.renderFromHTML("
", {loadTimeout: 2000})
+])
+ .then(function (paths) {
+ console.log('Created PDFs @', paths);
+ // manual clenup could be done here, but better use autocelan
+ // if you want a manual cleanup, disable autoclean by setting option: autoCleanFileAgeInSec = -1
+ // then do the cleanup manual; use a timeout to prevent deleting pending operations
+ // console.log("Deleted", url2pdf.cleanup(5)); // remove all files older than 5 seconds
+ })
+ .catch(function (err) {
+ console.error(err.stack);
+ });
diff --git a/index.js b/index.js
index 4fe90eb..e3b23a0 100644
--- a/index.js
+++ b/index.js
@@ -1,133 +1,163 @@
-/*jslint node: true */
-'use strict';
+var findRemove = require('find-remove'),
+ _ = require('lodash'),
+ phantom = require('phantom'),
+ q = require('q'),
+ // node intern modules
+ fs = require('fs'),
+ crypto = require('crypto'),
+ execSync = require('child_process').execSync,
+ path = require('path');
-var http = require("http");
-var phantom = require("phantom");
-var fs = require("fs");
-var q = require('q');
-var path = require('path');
-var findRemove = require('find-remove');
-var _ = require('lodash');
var _opts = {
- paperSize: {
- format: "A4",
- orientation: 'portrait',
- margin: '1cm'
- },
- saveDir: path.join(__dirname, "pdfTemp"),
- idLength: 30,
- possibleIdChars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- loadTimeout: 500,
- autoCleanFileAgeInSec: 20
+ paperSize: {
+ format: 'A4',
+ orientation: 'portrait',
+ margin: '1cm'
+ },
+ saveDir: path.join(__dirname, '/pdfTemp'),
+ idLength: 30,
+ possibleIdChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ loadTimeout: 500,
+ autoCleanFileAgeInSec: 20,
+ debug: false
};
module.exports = {
- opts: _opts,
- renderPdf: function renderpdf(url, opts) {
- return render(url, opts, "url");
- },
- renderFromHTML: function renderFromHTML(htmlString, opts) {
- return render(htmlString, opts, "htmlContent");
- },
- cleanup: _cleanup
-};
+ opts: _opts,
+ renderPdf: function renderpdf (url, opts) {
+ return render(url, opts, 'url');
+ },
+ renderFromHTML: function renderFromHTML (htmlString, opts) {
+ return render(htmlString, opts, 'htmlContent');
+ },
+ cleanup: _cleanup,
+ join: _join
+};
-function render(string, opts, renderType) {
- var deferred = q.defer();
- var page, fileName, ph, fullPath;
-
- opts = mergeOpts(opts);
- phantom.create(['--ignore-ssl-errors=yes'])
- .then(function(_ph) {
- ph = _ph;
- return ph.createPage();
- })
- .then(function(_page) {
- page = _page;
- return page.property("paperSize", opts.paperSize);
- })
- .then(function() {
- if (renderType == "url") {
- return page.open(string); // string = url path
- } else if (renderType == "htmlContent") {
- return page.property("content", string); // string = html doc as string
- } else {
- console.log("wrong render type: " + renderType);
- ph.exit();
- }
- })
- .then(function(status) {
- fileName = makeid(opts.idLength) + ".pdf";
- fullPath = opts.saveDir + "/" + fileName;
- return promiseWithTimeout(opts.loadTimeout);
- })
- .then(function() {
- return page.render(fullPath);
- })
- .then(function() {
- deferred.resolve(fullPath);
- })
- .catch(function(err) {
- deferred.reject(err);
- })
- .then(function() {
- ph.exit();
- if(0 < opts.autoCleanFileAgeInSec){
- _cleanup(opts.autoCleanFileAgeInSec);
- }
- });
- return deferred.promise;
+function render (string, opts, renderType) {
+ opts = mergeOpts(opts);
+
+ var deferred = q.defer(),
+ page, fileName, ph, fullPath,
+
+ // log phantoms output in debugging mode
+ phantomOpts = opts.debug ? {
+ logLevel: 'debug'
+ } : {};
+
+ phantom.create(['--ignore-ssl-errors=yes'], phantomOpts)
+ .then(function (_ph) {
+ ph = _ph;
+ return ph.createPage();
+ })
+ .then(function (_page) {
+ page = _page;
+
+ // log messages from phantom browser console in debugging mode
+ if (opts.debug) {
+ page.property('onConsoleMessage', function (msg) {
+ console.log('Phantom console Message:');
+ console.log(msg);
+ });
+ }
+
+ return page.property('paperSize', opts.paperSize);
+ })
+ .then(function () {
+ if (renderType === 'url') {
+ return page.open(string); // string = url path
+ } else if (renderType === 'htmlContent') {
+ return page.property('content', string); // string = html doc as string
+ } else {
+ console.log('wrong render type: ' + renderType);
+ ph.exit();
+ }
+ })
+ .then(function (status) {
+ fileName = makeid(opts.idLength) + '.pdf';
+ fullPath = opts.saveDir + '/' + fileName;
+ return promiseWithTimeout(opts.loadTimeout);
+ })
+ .then(function () {
+ return page.render(fullPath);
+ })
+ .then(function () {
+ deferred.resolve(fullPath);
+ })
+ .catch(function (err) {
+ deferred.reject(err);
+ })
+ .then(function () {
+ ph.exit();
+ if (opts.autoCleanFileAgeInSec > 0) {
+ _cleanup(opts.autoCleanFileAgeInSec);
+ }
+ });
+
+ return deferred.promise;
}
-
-function mergeOpts(newOpts) {
- if (newOpts) {
- return _.merge({}, _opts, newOpts);
- } else {
- return _opts;
- }
+function mergeOpts (newOpts) {
+ if (newOpts) {
+ return _.merge({}, _opts, newOpts);
+ } else {
+ return _opts;
+ }
}
-function promiseWithTimeout(duration) {
- var deferred = q.defer();
- setTimeout(deferred.resolve, duration);
- return deferred.promise;
+function promiseWithTimeout (duration) {
+ var deferred = q.defer();
+ setTimeout(deferred.resolve, duration);
+ return deferred.promise;
}
-function makeid(strLength) {
- if (!strLength) strLength = 30;
- var text = "";
- var possible = _opts.possibleIdChars;
+function makeid (strLength) {
+ if (!strLength) strLength = 30;
+ var text = '';
+ var possible = _opts.possibleIdChars;
- for (var i = 0; i < strLength; i++) {
- text += possible.charAt(Math.floor(Math.random() * possible.length));
- }
- return text;
+ for (var i = 0; i < strLength; i++) {
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
+ }
+ return text;
}
-function closure(fn) {
- var _arguments = arguments;
- delete arguments[0];
- return function() {
- fn.apply(_arguments);
- };
+function _cleanup (ageInSeconds, opts) {
+ opts = mergeOpts(opts);
+ return findRemove(opts.saveDir, {
+ age: {
+ seconds: ageInSeconds
+ }
+ });
}
-function _cleanup(ageInSeconds) {
- return findRemove(_opts.saveDir, {
- age: {
- seconds: ageInSeconds
- }
+function _join (filePathArray, exportUrl, onlyFile) {
+
+ exportUrl = exportUrl || _opts.saveDir;
+ exportUrl += crypto.randomBytes(20).toString('hex');
+
+ execSync('gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=' + exportUrl + ' ' + filePathArray.join(' '));
+
+ filePathArray.forEach(function (filePath) { // delete merged files
+ fs.unlinkSync(filePath);
});
+
+ if (onlyFile) { // read file in, delete file, return content
+ var fileContent = fs.readFileSync(exportUrl);
+ fs.unlinkSync(exportUrl);
+ return fileContent;
+ } else { // leave file and return url
+ return exportUrl;
+ }
}
diff --git a/package.json b/package.json
index a849980..50cded5 100644
--- a/package.json
+++ b/package.json
@@ -1,51 +1,36 @@
{
- "name": "url2pdf",
- "version": "0.5.0",
+ "name": "url2pdf-plus",
+ "version": "0.5.7",
"description": "Fetches a URL and converts HTML to PDF files using PhantomJS",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": "Ryan Knell",
- "license": "ISC",
- "dependencies": {
- "bindings": "^1.2.1",
- "find-remove": "^0.2.10",
- "lodash": "^4.8.1",
- "phantom": "^2.0.9",
- "q": "^1.1.2"
+ "author": {
+ "name": "Felix Furtmayr"
},
- "_shasum": "cce8fd909f7464b54f16b91a69d1fd18c650edd8",
- "_from": "url2pdf@latest",
- "_npmVersion": "2.1.10",
- "_nodeVersion": "0.10.22",
- "_npmUser": {
- "name": "ryanknell",
- "email": "sales@snappyapps.com.au"
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:FelixFurtmayr/url2pdf.git"
},
"maintainers": [
- "ryanknell