Skip to content

Commit 76a6ca4

Browse files
committed
Merge pull request #6 from marcbachmann/windows-support
Windows support fixes #5
2 parents 1b23276 + bc639bf commit 76a6ca4

6 files changed

Lines changed: 109 additions & 74 deletions

File tree

Gruntfile.coffee

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
module.exports = (grunt) ->
22

33
grunt.initConfig
4-
mochaTest:
4+
mochacli:
55
test:
66
options:
77
ui: 'bdd'
88
reporter: 'spec'
9-
require: ['coffee-script']
9+
compilers: ['coffee:coffee-script/register']
1010
slow: '1ms'
11-
12-
src: ['test/**/*.coffee']
11+
timeout: '10s'
12+
files: 'test/**/*'
1313

1414
watch:
1515
tests:
1616
files: ['test/**/*.coffee', 'lib/**/*.coffee']
17-
tasks: ['mochaTest']
17+
tasks: ['mochacli']
1818

1919

20-
grunt.loadNpmTasks('grunt-mocha-test')
20+
grunt.loadNpmTasks('grunt-mocha-cli')
2121
grunt.loadNpmTasks('grunt-contrib-watch')
2222

23-
grunt.registerTask('test', ['mochaTest', 'watch'])
23+
grunt.registerTask('test', ['mochacli', 'watch'])

lib/index.coffee

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,35 @@ spawn = require('child_process').spawn
33
path = require('path')
44
phantomjs = require('phantomjs')
55

6-
#
6+
#
77
# phantomjs version 1.8.1 and later should work. Ubuntu has some problems when trying to buffer to /dev/stdout
8-
#
8+
#
99
# Create a PDF file out of an html string.
10-
#
10+
#
1111
# Regions for the PDF page are:
12-
#
12+
#
1313
# - Page Header -> document.getElementById('pageHeader')
1414
# - Page Content -> document.getElementById('pageContent')
1515
# - Page Footer -> document.getElementById('pageFooter')
1616
#
1717
# When no #pageContent is available, phantomjs will use document.body as pdf content
18-
script = path.join(__dirname, 'scripts/pdf_a4_portrait.coffee')
18+
script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee')
1919

2020
exports.create = (string, options, callback) ->
2121
if arguments.length == 2
2222
callback = options
2323
options = {}
2424

25-
return callback(new Error("Can't create pdf without content")) unless string?.length
26-
child = spawn(phantomjs.path, [options.script || script, string.length, JSON.stringify(options)])
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])
2727
stdout = []
2828
stderr = []
2929

3030
timeout = setTimeout ->
3131
child.stdin.end()
3232
child.kill()
33-
stderr = [new Buffer('PDF creation timeout. PDF generation script did not end.')] unless stderr.length
34-
, parseInt(options.timeout) || 10000
33+
stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')] unless stderr.length
34+
, parseInt(options.timeout) || 30000
3535

3636
child.stdout.on 'data', (buffer) ->
3737
stdout.push(buffer)
@@ -45,23 +45,28 @@ exports.create = (string, options, callback) ->
4545
# Clean up the timeout cause the process ended anyways
4646
clearTimeout(timeout)
4747
if (stderr.length || code) > 0
48-
error = new Error(Buffer.concat(stderr).toString())
48+
error = new Error(Buffer.concat(stderr).toString() || 'html-pdf: Unknown Error')
4949
return callback(error)
5050

5151
file = Buffer.concat(stdout)
52-
if isFile = /^\%PDF/.test(file.slice(0, 4).toString())
53-
callback(null, file)
52+
isFileBuffer = /^\%PDF/.test(file.slice(0, 4).toString())
5453

55-
else
54+
if options.filename
55+
callback(null, file.toString())
56+
57+
else if !isFileBuffer
5658
filename = file.toString()
5759
fs.readFile filename, (err, buffer) ->
5860
return callback(err) if err
59-
60-
# Only delete file when options.filename is not defined
61-
unless options.filename
62-
fs.unlink filename, (err) ->
63-
callback(err, buffer)
64-
else
61+
fs.unlink filename, (err) ->
6562
callback(err, buffer)
6663

67-
child.stdin.write(string, 'utf8')
64+
else
65+
callback(null, file)
66+
67+
68+
content =
69+
html: string
70+
options: options
71+
72+
child.stdin.write(JSON.stringify(content)+'\n', 'utf8')

lib/index.js

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ path = require('path');
88

99
phantomjs = require('phantomjs');
1010

11-
script = path.join(__dirname, 'scripts/pdf_a4_portrait.coffee');
11+
script = path.join(__dirname, 'scripts', 'pdf_a4_portrait.coffee');
1212

1313
exports.create = function(string, options, callback) {
14-
var child, stderr, stdout, timeout;
14+
var child, content, stderr, stdout, timeout;
1515
if (arguments.length === 2) {
1616
callback = options;
1717
options = {};
1818
}
1919
if (!(string != null ? string.length : void 0)) {
20-
return callback(new Error("Can't create pdf without content"));
20+
return callback(new Error("html-pdf: Can't create a pdf without content"));
2121
}
22-
child = spawn(phantomjs.path, [options.script || script, string.length, JSON.stringify(options)]);
22+
child = spawn(phantomjs.path, [options.script || script]);
2323
stdout = [];
2424
stderr = [];
2525
timeout = setTimeout(function() {
2626
child.stdin.end();
2727
child.kill();
2828
if (!stderr.length) {
29-
return stderr = [new Buffer('PDF creation timeout. PDF generation script did not end.')];
29+
return stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')];
3030
}
31-
}, parseInt(options.timeout) || 10000);
31+
}, parseInt(options.timeout) || 30000);
3232
child.stdout.on('data', function(buffer) {
3333
return stdout.push(buffer);
3434
});
@@ -38,30 +38,33 @@ exports.create = function(string, options, callback) {
3838
return child.kill();
3939
});
4040
child.on('exit', function(code) {
41-
var error, file, filename, isFile;
41+
var error, file, filename, isFileBuffer;
4242
clearTimeout(timeout);
4343
if ((stderr.length || code) > 0) {
44-
error = new Error(Buffer.concat(stderr).toString());
44+
error = new Error(Buffer.concat(stderr).toString() || 'html-pdf: Unknown Error');
4545
return callback(error);
4646
}
4747
file = Buffer.concat(stdout);
48-
if (isFile = /^\%PDF/.test(file.slice(0, 4).toString())) {
49-
return callback(null, file);
50-
} else {
48+
isFileBuffer = /^\%PDF/.test(file.slice(0, 4).toString());
49+
if (options.filename) {
50+
return callback(null, file.toString());
51+
} else if (!isFileBuffer) {
5152
filename = file.toString();
5253
return fs.readFile(filename, function(err, buffer) {
5354
if (err) {
5455
return callback(err);
5556
}
56-
if (!options.filename) {
57-
return fs.unlink(filename, function(err) {
58-
return callback(err, buffer);
59-
});
60-
} else {
57+
return fs.unlink(filename, function(err) {
6158
return callback(err, buffer);
62-
}
59+
});
6360
});
61+
} else {
62+
return callback(null, file);
6463
}
6564
});
66-
return child.stdin.write(string, 'utf8');
65+
content = {
66+
html: string,
67+
options: options
68+
};
69+
return child.stdin.write(JSON.stringify(content) + '\n', 'utf8');
6770
};

lib/scripts/pdf_a4_portrait.coffee

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
1-
sys = require('system')
1+
system = require('system')
22
webpage = require('webpage')
33

4+
# Error handler
5+
exit = (error) ->
6+
message = error if typeof error is 'string'
7+
system.stderr.write("html-pdf: #{message || "Unknown Error #{error}"}\n") if error
8+
phantom.exit(if error then 1 else 0)
9+
10+
11+
# Force cleanup after 2 minutes
12+
setTimeout ->
13+
exit('Force timeout')
14+
, 120000
15+
16+
17+
# Load configurations from stdin
18+
json = JSON.parse(system.stdin.readLine())
19+
exit('Did not receive any html') if !json.html?.trim()
20+
21+
options = json.options
422
page = webpage.create()
5-
bufferSize = sys.args[1]
6-
options = {}
7-
options = JSON.parse(sys.args[2]) if typeof sys.args[2] is 'string'
8-
page.content = sys.stdin.read(bufferSize)
23+
page.content = json.html
924

1025

1126
# Set up content
@@ -71,17 +86,15 @@ page.onLoadFinished = (status) ->
7186
type: options.type || 'pdf'
7287
quality: options.quality || 75
7388

74-
# Option 1: Output file to stdout
75-
# Not working in Ubuntu 12.04 (at least not in my environment)
76-
if options.buffer
77-
page.render('/dev/stdout', fileOptions)
78-
89+
if !options.buffer
90+
filename = options.filename || ("#{options.directory || '/tmp'}/html-pdf-#{system.pid}.#{fileOptions.type}")
91+
page.render(filename, fileOptions)
92+
system.stdout.write(filename)
7993

80-
# Option 2: Output filename to stdout
94+
# Deprecated options.buffer method
8195
else
82-
filename = options.filename || ("#{options.directory || '/tmp'}/html-pdf-#{sys.pid}-#{bufferSize}.#{fileOptions.type}")
83-
page.render(filename, fileOptions)
84-
sys.stdout.write(filename)
96+
system.stderr.write('html-pdf: options.buffer is deprecated. Because of compatibility issues this method is longer supported.\n')
97+
page.render('/dev/stdout', fileOptions)
8598

8699

87-
phantom.exit(0)
100+
exit(null)

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@
1212
"author": "Marc Bachmann",
1313
"license": "MIT",
1414
"devDependencies": {
15-
"coffee-script": "^1.7.1",
1615
"chai": "^1.9.1",
17-
"grunt-mocha-test": "^0.10.2",
18-
"grunt": "^0.4.4",
19-
"mocha": "^1.18.2",
20-
"grunt-contrib-watch": "^0.6.1"
16+
"coffee-script": "^1.7.1",
17+
"grunt": "^0.4.5",
18+
"grunt-cli": "^0.1.13",
19+
"grunt-contrib-watch": "^0.6.1",
20+
"grunt-mocha-cli": "^1.11.0",
21+
"mocha": "^1.18.2"
2122
},
2223
"dependencies": {
23-
"phantomjs": "^1.9.7-8"
24+
"phantomjs": "^1.9.8"
2425
},
2526
"repository": {
2627
"type": "git",

test/create.coffee

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe 'html-pdf', ->
1717
<div id="pageContent">Content</div>
1818
<div id="pageFooter">Footer</div>
1919
</body>
20-
</html>
20+
</html>
2121
"""
2222

2323
it 'throws error when passing null', (done) ->
@@ -40,17 +40,29 @@ describe 'html-pdf', ->
4040

4141
it 'does not throw an error when succeeding', (done) ->
4242
pdf.create @html, (error, pdf) =>
43-
@pdf = pdf
4443
expect(error).to.be.null
45-
fs.writeFile(path.join(__dirname,'simple.pdf'), pdf)
4644
done()
4745

48-
it 'returns a buffer', ->
49-
expect(Buffer.isBuffer(@pdf), 'Should be a buffer').to.be.equal(true)
5046

47+
it 'buffer must be returned when no filename specified', (done) ->
48+
pdf.create @html, (error, pdf) =>
49+
expect(pdf).to.be.defined
50+
done()
51+
52+
53+
it 'returns a pdf buffer', (done) ->
54+
pdf.create @html, (error, pdf) =>
55+
expect(Buffer.isBuffer(pdf), 'Expect to be a pdf Buffer').to.be.equal(true)
56+
expect(/^\%PDF-1.4/.test(pdf.toString()), 'Has a PDF header').to.be.equal(true)
57+
done()
58+
59+
60+
it 'saves the pdf to a destination', (done) ->
61+
file = path.join(__dirname,'simple.pdf')
62+
pdf.create @html, filename: file, (error, pdf) =>
63+
expect(fs.existsSync(path.join(__dirname,'simple.pdf'))).to.equal(true)
64+
done()
5165

52-
it 'returns a pdf buffer', ->
53-
expect(/^\%PDF-1.4/.test(@pdf.toString()), 'Has a PDF header').to.be.equal(true)
5466

5567
it 'works with a custom page size and footer', (done) ->
5668
options =
@@ -71,8 +83,9 @@ describe 'html-pdf', ->
7183
options =
7284
width: '50mm'
7385
height: '90mm'
86+
filename: path.join(__dirname,'businesscard.pdf')
7487

7588
pdf.create html, options,(error, pdf) =>
76-
fs.writeFile(path.join(__dirname,'businesscard.pdf'), pdf)
7789
expect(error).to.be.null
90+
expect(fs.existsSync(options.filename)).to.equal(true)
7891
done()

0 commit comments

Comments
 (0)