A command line tool to generate PDF from URL, HTML or Markdown files with electron.
I have a blog post explain why PDF Generation On The Web
Production ready? See it in action for the Myanmar Election!
npm install electron-pdf -g
For gnu/linux installations without a graphical environment:
$ sudo apt-get install xvfb # or equivalent
$ export DISPLAY=':99.0'
$ Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
$ electron-pdf ...
There is also an example docker machine here.
Electron PDF can be used inside of an application, or more commonly as the engine for a pdf rendering service. For instance, to handle http requests using Express. The following snipppets show you how you can get started.
In package.json
"start": "DEBUG=electronpdf:* electron index.js",
"watch": "DEBUG=electronpdf:* nodemon --exec electron index.js"
var ElectronPDF = require('electron-pdf')
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
app.use(bodyParser.json())
var exporter = new ElectronPDF()
exporter.on('charged', () => {
//Only start the express server once the exporter is ready
app.listen(port, hostname, function() {
console.log(`Export Server running at http://${hostname}:${port}`);
})
})
exporter.start()
app.post('/pdfexport', function(req,res){
// derive job arguments from request here
//
const jobOptions = {
/**
r.results[] will contain the following based on inMemory
false: the fully qualified path to a PDF file on disk
true: The Buffer Object as returned by Electron
Note: the default is false, this can not be set using the CLI
*/
inMemory: false
}
const options = {
pageSize : "A4"
}
exporter.createJob(source, target, options, jobOptions).then( job => {
job.on('job-complete', (r) => {
console.log('pdf files:', r.results)
// Process the PDF file(s) here
})
job.render()
})
})
If you set the inMemory
setting to true, you must also set closeWindow=true
or you will get a segmentation fault anytime the window is closed before the buffer
is sent on the response. You then need to invoke job.destroy
to close the window.
Sample Code:
const jobOptions = { inMemory: true, closeWindow: false }
exporter.createJob(source, target, options, jobOptions).then( job => {
job.on('job-complete', (r) => {
//Send the Buffer here
process.nextTick(() => {job.destroy()})
})
})
The API is designed to emit noteworthy events rather than use callbacks. Full documentation of all events is a work in progress.
For Ad-hoc conversions, Electron PDF comes with support for a CLI.
$ electron-pdf index.html ~/Desktop/index.pdf
$ electron-pdf index.md ~/Desktop/index.pdf
$ electron-pdf index.html ~/Desktop/index.pdf -c my-awesome-css.css
$ electron-pdf https://fraserxu.me ~/Desktop/fraserxu.pdf
Electron PDF gives you complete control of how the BrowserWindow should be configured, and when the window contents should be captured.
The BrowserWindow supports many options which you
may define by passing a JSON Object to the --browserConfig
option.
Some common use cases may include:
height
andwidth
- electron-pdf calculates the browser height and width based off of the dimensions of PDF page size multiplied by the HTML standard of 96 pixels/inch. So only set these values if you need to override this behaviorshow
- to display the browser window during generation
$ electron-pdf https://fraserxu.me ~/Desktop/fraserxu.pdf --browserConfig '{"show":true}'
electron-pdf ./index.html ~/Desktop/README.pdf -e
In your application, at the point which the view is ready for rendering
document.body.dispatchEvent(new Event('view-ready'))
Warning: It is possible that your application will be ready and emit the event before the main electron process has had a chance execute the javascript in the renderer process which listens for this event.
If you are finding that the event is not effective and your page waits until the full timeout has occurred, then you should use setInterval
to emit the event until it is acknowledged like so:
var eventEmitInterval = setInterval(function () {
document.body.dispatchEvent(new Event('view-ready'))
}, 25)
document.body.addEventListener('view-ready-acknowledged', function(){
clearInterval(eventEmitInterval)
})
When the main process first receives your ready event it will emit a single acknowlegement on document.body
with whatever event name you are using suffixed with -acknowledged
. So the default would be view-ready-acknowledged
If the page you are rending is under your control, and you wish to modify the behavior of the rendering process you can use a CustomEvent and an observer that will be triggered after the view is ready but before it is captured.
document.body.dispatchEvent(new CustomEvent('view-ready', { detail: {layout: landscape} }))
As an example, suppose you wanted to change the orientation of the PDF
job.observeReadyEvent( (detail) => {
return new Promise( (resolve,reject) => {
if( detail && detail.landscape ){
job.changeArgValue('landscape', true)
}
resolve()
})
})
Electron PDF exposes the printToPDF settings (i.e. pageSize, orientation, margins, etc.) available from the Electron API. See the following options for usage.
A command line tool to generate PDF from URL, HTML or Markdown files
Options
--help Show this help
--version Current version of package
-i | --input String - The path to the HTML file or url
-o | --output String - The path of the output PDF
--browserConfig String - A valid JSON String that will be parsed into the options passed to electron.BrowserWindow
-c | --css String - The path to custom CSS
-b | --printBackground Boolean - Whether to print CSS backgrounds.
false - default
-s | --printSelectionOnly Boolean - Whether to print selection only
false - default
-p | --pageSize String - Can be A3, A4, A5, Legal, Letter, Tabloid or an Object containing height and width in microns
"A4" - default
-l | --landscape Boolean - true for landscape, false for portrait (don't pass a string on the CLI, just the `-l` flag)
false - default
-m | --marginsType Integer - Specify the type of margins to use
0 - default margins
1 - no margins (electron-pdf default setting)
2 - minimum margins
-d | --disableCache Disable HTTP caching
-w | --outputWait Integer – Time to wait (in MS) between page load and PDF creation. If used in conjunction with -e this will override the default timeout of 10 seconds
-e | --waitForJSEvent String - The name of the event to wait before PDF creation
'view-ready' - default
You can see some additional logging (if you're getting errors or unexpected output) by setting DEBUG=electron*
For example: DEBUG=electron* electron-pdf <input> <output> -l
Usage
$ electron-pdf <input> <output>
$ electron-pdf <input> <output> -l
Examples
$ electron-pdf http://fraserxu.me ~/Desktop/fraserxu.pdf
$ electron-pdf ./index.html ~/Desktop/index.pdf
$ electron-pdf ./README.md ~/Desktop/README.pdf -l
$ electron-pdf ./README.md ~/Desktop/README.pdf -l -c my-awesome-css.css
Inspired by electron-mocha
Want to use the same options, but export to PNG or snapshot the rendered HTML? Just set the output filename to end in .png or .html instead!
Examples
$ electron-pdf http://fraserxu.me ~/Desktop/fraserxu.pdf
$ electron-pdf http://fraserxu.me ~/Desktop/fraserxu.html
$ electron-pdf http://fraserxu.me ~/Desktop/fraserxu.png
If you need powerpoint support, pdf-powerpoint picks up where Electron PDF leaves off by converting each page in the PDF to a PNG and placing them on individual slides.
MIT