I'm currently trying to generate a PDF document from a HTML page through Node & PhantomJS.
If my page contains local resources, or only static things, it works fine :
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="StyleSheet" media="screen" href="./style.css" />
<link rel="StyleSheet" media="print" href="./print.css" />
</head>
<body>
<h1>The title</h1>
<p>hai <span class="foo">lol <span class="bar">I'm generating</span> a pdf</span> !</p>
<p class="centre"><img src="http://www.gratuit-en-ligne.com/telecharger-gratuit-en-ligne/telecharger-image-wallpaper-gratuit/image-wallpaper-animaux/img/images/image-wallpaper-animaux-autruche.jpg" /></p>
<canvas id="test_canvas" width="200px" height="100px"/>
<script>
setTimeout(function () {
var ctx = document.getElementById('test_canvas').getContext('2d');
ctx.fillStyle = '#FF0000';
ctx.fillRect(0, 0, 150, 75);
}, 1000);
setTimeout(function () {
evt = document.createEvent('CustomEvent');
evt.initEvent('pdfTrigger', true, false);
document.dispatchEvent(evt);
}, 3000);
</script>
</body>
</html>
So here, the image is correctly rendered, and the stylesheets are also correctly rendered. But if I add an inclusion from a distant image, or a distant script (something beginning with either //
, either http://
or https://
, even if it is directed towards my local environment), the content is not loaded :
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="StyleSheet" media="screen" href="./style.css" />
<link rel="StyleSheet" media="print" href="./print.css" />
</head>
<body>
<h1>The title</h1>
<p>hai <span class="foo">lol <span class="bar">I'm generating</span> a pdf</span> !</p>
<p class="centre"><img src="http://upload.wikimedia.org/wikipedia/commons/7/7c/Ostrich,_mouth_open.jpg" /></p>
<script>
setTimeout(function () {
evt = document.createEvent('CustomEvent');
evt.initEvent('pdfTrigger', true, false);
document.dispatchEvent(evt);
}, 3000);
</script>
</body>
</html>
The image is not rendered ; if I try with a jQuery include from a cdn and some jQuery code (like firing an event through $(document).trigger('pdfTrigger')
), it says ReferenceError: Can't find variable: $
, and thus the event is never fired. If I include it in my html file on a local resource (like <script src="./jquery.min.css"></script>
), the error disappear but the event is never fired...
Here is the phantomjs script i'm using :
/**
* Render a PDF from an HTML file
*
* @author Baptiste Clavié <baptiste@wisembly.com>
* Adapted from PhantomJs' example "rasterize.js"
*/
var orientation = 'portrait',
system = require('system'),
args = system.args.slice(1);
if (args.length < 2 || args.length > 3) {
system.stderr.writeLine('Usage: rasterize.js source output [orientation]');
system.stderr.writeLine(' source : html source to put in the pdf');
system.stderr.writeLine(' output : output when the pdf will be written');
system.stderr.writeLine(' orientation : document orientation (either portrait or landscape');
phantom.exit((args.length === 1 & args[0] === '--help') ? 0 : 1);
}
if (typeof args[2] !== 'undefined') {
if (-1 === ['portrait', 'landscape'].indexOf(args[2])) {
system.stderr.writeLine('Invalid argument for [orientation]');
system.stderr.write('Expected either "portrait", either "landscape" ; got "' + args[2] + '"');
phantom.exit(1);
}
orientation = args[2];
}
var page = require('webpage').create(),
identifier = '___RENDER____';
page.paperSize = { format: 'A4', orientation: orientation, margin: '1cm' };
page.onInitialized = function() {
page.evaluate(function(identifier) {
document.addEventListener('pdfTrigger', function () {
console.log(identifier);
}, false);
}, identifier);
};
page.onError = function (msg, trace) {
system.stderr.writeLine(msg);
trace.forEach(function(item) {
system.stderr.writeLine(' ' + item.file + ':' + item.line);
});
phantom.exit(1);
}
page.onConsoleMessage = function (msg) {
console.log(msg);
if (msg !== identifier) {
return;
}
page.render(args[1], { format: 'pdf' });
phantom.exit(0);
}
page.open(args[0], function (status) {
if (status !== 'success') {
system.stderr.write('Unable to load the file "' + args[0] + '"');
phantom.exit(1);
}
});
To launch my script, i'm using the following command : phantomjs rasterize.pdf test.html test.pdf
to sum up, it seems I can't load any external things from a html when trying to render it in Phantom, and jQuery is not recognized (and probably some other scripts ?)
Any idea ? If more precision if needed, please don't hesitate.