Skip to content

Commit d26ae56

Browse files
committed
Add new API
1 parent ee7d27c commit d26ae56

7 files changed

Lines changed: 218 additions & 132 deletions

File tree

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@ pdf.create(html, { width: '50mm', height: '90mm'}, function(err, buffer) {
1818
```
1919

2020
## API
21-
Currently there is only one function
21+
```js
22+
pdf(html [, options], callback)
23+
pdf(html [, options]).exec(callback)
24+
pdf(html [, options]).toBuffer(callback)
25+
pdf(html [, options]).toStream()
26+
27+
// for backward compatibility
28+
pdf.create(html [, options], callback)
29+
30+
```
31+
32+
2233
```javascript
2334
var pdf = require('html-pdf');
2435
var callback = function(err, buffer){}

lib/index.coffee

Lines changed: 14 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,23 @@
1-
fs = require('fs')
2-
spawn = require('child_process').spawn
3-
path = require('path')
4-
phantomjs = require('phantomjs')
1+
PDF = require('./pdf')
52

6-
#
7-
# phantomjs version 1.8.1 and later should work. Ubuntu has some problems when trying to buffer to /dev/stdout
8-
#
9-
# Create a PDF file out of an html string.
10-
#
11-
# Regions for the PDF page are:
12-
#
13-
# - Page Header -> document.getElementById('pageHeader')
14-
# - Page Content -> document.getElementById('pageContent')
15-
# - Page Footer -> document.getElementById('pageFooter')
16-
#
17-
# When no #pageContent is available, phantomjs will use document.body as pdf content
18-
script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee')
3+
module.exports = (html, options, callback) ->
4+
if arguments.length == 1
5+
return new PDF(html)
6+
7+
if arguments.length == 2 && typeof options != 'function'
8+
return new PDF(html, options)
199

20-
exports.create = (string, options, callback) ->
2110
if arguments.length == 2
2211
callback = options
2312
options = {}
2413

25-
return callback(new Error("html-pdf: Can't create a pdf without content")) unless string?.length
26-
child = spawn(phantomjs.path, [options.script || script])
27-
stdout = []
28-
stderr = []
29-
30-
timeout = setTimeout ->
31-
child.stdin.end()
32-
child.kill()
33-
stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')] unless stderr.length
34-
, parseInt(options.timeout) || 30000
35-
36-
child.stdout.on 'data', (buffer) ->
37-
stdout.push(buffer)
38-
39-
child.stderr.on 'data', (buffer) ->
40-
stderr.push(buffer)
41-
child.stdin.end()
42-
child.kill()
43-
44-
child.on 'exit', (code) ->
45-
# Clean up the timeout cause the process ended anyways
46-
clearTimeout(timeout)
47-
if (stderr.length || code) > 0
48-
error = new Error(Buffer.concat(stderr).toString() || 'html-pdf: Unknown Error')
49-
return callback(error)
50-
51-
file = Buffer.concat(stdout)
52-
isFileBuffer = /^\%PDF/.test(file.slice(0, 4).toString())
53-
54-
if options.filename
55-
callback(null, file.toString())
56-
57-
else if !isFileBuffer
58-
filename = file.toString()
59-
fs.readFile filename, (err, buffer) ->
60-
return callback(err) if err
61-
fs.unlink filename, (err) ->
62-
callback(err, buffer)
63-
64-
else
65-
callback(null, file)
14+
try
15+
pdf = new PDF(html, options)
16+
catch err
17+
return callback(err)
6618

19+
pdf.exec(callback)
6720

68-
content =
69-
html: string
70-
options: options
7121

72-
child.stdin.write(JSON.stringify(content)+'\n', 'utf8')
22+
module.exports.create = ->
23+
module.exports.apply(undefined, arguments)

lib/index.js

Lines changed: 20 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,28 @@
1-
var fs, path, phantomjs, script, spawn;
1+
var PDF;
22

3-
fs = require('fs');
3+
PDF = require('./pdf');
44

5-
spawn = require('child_process').spawn;
6-
7-
path = require('path');
8-
9-
phantomjs = require('phantomjs');
10-
11-
script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee');
12-
13-
exports.create = function(string, options, callback) {
14-
var child, content, stderr, stdout, timeout;
5+
module.exports = function(html, options, callback) {
6+
var err, pdf;
7+
if (arguments.length === 1) {
8+
return new PDF(html);
9+
}
10+
if (arguments.length === 2 && typeof options !== 'function') {
11+
return new PDF(html, options);
12+
}
1513
if (arguments.length === 2) {
1614
callback = options;
1715
options = {};
1816
}
19-
if (!(string != null ? string.length : void 0)) {
20-
return callback(new Error("html-pdf: Can't create a pdf without content"));
17+
try {
18+
pdf = new PDF(html, options);
19+
} catch (_error) {
20+
err = _error;
21+
return callback(err);
2122
}
22-
child = spawn(phantomjs.path, [options.script || script]);
23-
stdout = [];
24-
stderr = [];
25-
timeout = setTimeout(function() {
26-
child.stdin.end();
27-
child.kill();
28-
if (!stderr.length) {
29-
return stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')];
30-
}
31-
}, parseInt(options.timeout) || 30000);
32-
child.stdout.on('data', function(buffer) {
33-
return stdout.push(buffer);
34-
});
35-
child.stderr.on('data', function(buffer) {
36-
stderr.push(buffer);
37-
child.stdin.end();
38-
return child.kill();
39-
});
40-
child.on('exit', function(code) {
41-
var error, file, filename, isFileBuffer;
42-
clearTimeout(timeout);
43-
if ((stderr.length || code) > 0) {
44-
error = new Error(Buffer.concat(stderr).toString() || 'html-pdf: Unknown Error');
45-
return callback(error);
46-
}
47-
file = Buffer.concat(stdout);
48-
isFileBuffer = /^\%PDF/.test(file.slice(0, 4).toString());
49-
if (options.filename) {
50-
return callback(null, file.toString());
51-
} else if (!isFileBuffer) {
52-
filename = file.toString();
53-
return fs.readFile(filename, function(err, buffer) {
54-
if (err) {
55-
return callback(err);
56-
}
57-
return fs.unlink(filename, function(err) {
58-
return callback(err, buffer);
59-
});
60-
});
61-
} else {
62-
return callback(null, file);
63-
}
64-
});
65-
content = {
66-
html: string,
67-
options: options
68-
};
69-
return child.stdin.write(JSON.stringify(content) + '\n', 'utf8');
23+
return pdf.exec(callback);
24+
};
25+
26+
module.exports.create = function() {
27+
return module.exports.apply(void 0, arguments);
7028
};

lib/pdf.coffee

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
fs = require('fs')
2+
childprocess = require('child_process')
3+
path = require('path')
4+
assert = require('assert')
5+
phantomjs = require('phantomjs')
6+
7+
#
8+
# phantomjs version 1.8.1 and later should work.
9+
#
10+
# Create a PDF file out of an html string.
11+
#
12+
# Regions for the PDF page are:
13+
#
14+
# - Page Header -> document.getElementById('pageHeader')
15+
# - Page Content -> document.getElementById('pageContent')
16+
# - Page Footer -> document.getElementById('pageFooter')
17+
#
18+
# When no #pageContent is available, phantomjs will use document.body as pdf content
19+
module.exports = class PDF
20+
21+
constructor: (@html, @options={}) ->
22+
if @options.script
23+
@script = path.normalize(@options.script)
24+
else
25+
@script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee')
26+
27+
@options.filename = path.resolve(@options.filename) if @options.filename
28+
assert(@html?.length, "html-pdf: Can't create a pdf without content")
29+
30+
31+
toBuffer: (callback) ->
32+
@exec (err, res) ->
33+
return callback(err) if err
34+
fs.readFile(res.filename, callback)
35+
36+
37+
toStream: ->
38+
stream = new fs.ReadStream
39+
@exec (err, res) ->
40+
return callback(err) if err
41+
fs.createReadStream(res.filename).pipe(stream)
42+
stream
43+
44+
45+
exec: (callback) ->
46+
child = childprocess.spawn(phantomjs.path, [@script])
47+
stdout = []
48+
stderr = []
49+
50+
timeout = setTimeout ->
51+
child.stdin.end()
52+
child.kill()
53+
stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')] unless stderr.length
54+
, parseInt(@options.timeout) || 30000
55+
56+
child.stdout.on 'data', (buffer) ->
57+
stdout.push(buffer)
58+
59+
child.stderr.on 'data', (buffer) ->
60+
stderr.push(buffer)
61+
child.stdin.end()
62+
child.kill()
63+
64+
child.on 'exit', (code) ->
65+
clearTimeout(timeout)
66+
if code || stderr.length
67+
err = new Error(Buffer.concat(stderr).toString() or 'html-pdf: Unknown Error')
68+
return callback(err)
69+
else
70+
filename = Buffer.concat(stdout).toString()?.trim()
71+
callback(null, {filename})
72+
73+
child.stdin.write(JSON.stringify({@html, @options})+'\n', 'utf8')
74+

lib/pdf.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
var PDF, assert, childprocess, fs, path, phantomjs;
2+
3+
fs = require('fs');
4+
5+
childprocess = require('child_process');
6+
7+
path = require('path');
8+
9+
assert = require('assert');
10+
11+
phantomjs = require('phantomjs');
12+
13+
module.exports = PDF = (function() {
14+
function PDF(html, options) {
15+
var _ref;
16+
this.html = html;
17+
this.options = options != null ? options : {};
18+
if (this.options.script) {
19+
this.script = path.normalize(this.options.script);
20+
} else {
21+
this.script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee');
22+
}
23+
if (this.options.filename) {
24+
this.options.filename = path.resolve(this.options.filename);
25+
}
26+
assert((_ref = this.html) != null ? _ref.length : void 0, "html-pdf: Can't create a pdf without content");
27+
}
28+
29+
PDF.prototype.toBuffer = function(callback) {
30+
return this.exec(function(err, res) {
31+
if (err) {
32+
return callback(err);
33+
}
34+
return fs.readFile(res.filename, callback);
35+
});
36+
};
37+
38+
PDF.prototype.toStream = function() {
39+
var stream;
40+
stream = new fs.ReadStream;
41+
this.exec(function(err, res) {
42+
if (err) {
43+
return callback(err);
44+
}
45+
return fs.createReadStream(res.filename).pipe(stream);
46+
});
47+
return stream;
48+
};
49+
50+
PDF.prototype.exec = function(callback) {
51+
var child, stderr, stdout, timeout;
52+
child = childprocess.spawn(phantomjs.path, [this.script]);
53+
stdout = [];
54+
stderr = [];
55+
timeout = setTimeout(function() {
56+
child.stdin.end();
57+
child.kill();
58+
if (!stderr.length) {
59+
return stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')];
60+
}
61+
}, parseInt(this.options.timeout) || 30000);
62+
child.stdout.on('data', function(buffer) {
63+
return stdout.push(buffer);
64+
});
65+
child.stderr.on('data', function(buffer) {
66+
stderr.push(buffer);
67+
child.stdin.end();
68+
return child.kill();
69+
});
70+
child.on('exit', function(code) {
71+
var err, filename, _ref;
72+
clearTimeout(timeout);
73+
if (code || stderr.length) {
74+
err = new Error(Buffer.concat(stderr).toString() || 'html-pdf: Unknown Error');
75+
return callback(err);
76+
} else {
77+
filename = (_ref = Buffer.concat(stdout).toString()) != null ? _ref.trim() : void 0;
78+
return callback(null, {
79+
filename: filename
80+
});
81+
}
82+
});
83+
return child.stdin.write(JSON.stringify({
84+
html: this.html,
85+
options: this.options
86+
}) + '\n', 'utf8');
87+
};
88+
89+
return PDF;
90+
91+
})();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "html-pdf",
33
"version": "0.3.0",
44
"description": "HTML to PDF converter that uses phantomjs",
5-
"main": "index.js",
5+
"main": "lib/index.js",
66
"directories": {
77
"test": "test"
88
},

0 commit comments

Comments
 (0)