Highly scalable html conversion using electron workers 🚀
Switch branches/tags
greenkeeper-debug-2.3.0 greenkeeper-debug-2.3.1 greenkeeper-debug-2.3.2 greenkeeper-debug-2.3.3 greenkeeper-electron-prebuilt-1.2.2 greenkeeper-electron-prebuilt-1.2.3 greenkeeper-electron-prebuilt-1.2.4 greenkeeper-electron-prebuilt-1.2.5 greenkeeper-electron-prebuilt-1.2.6 greenkeeper-electron-prebuilt-1.2.7 greenkeeper-electron-prebuilt-1.2.8 greenkeeper-electron-prebuilt-1.3.0 greenkeeper-electron-prebuilt-1.3.1 greenkeeper-electron-prebuilt-1.3.2 greenkeeper-electron-prebuilt-1.3.3 greenkeeper-electron-prebuilt-1.3.4 greenkeeper-electron-prebuilt-1.3.5 greenkeeper-electron-prebuilt-1.3.7 greenkeeper-electron-prebuilt-1.3.8 greenkeeper-electron-prebuilt-1.3.9 greenkeeper-electron-prebuilt-1.3.10 greenkeeper-electron-prebuilt-1.3.11 greenkeeper-electron-prebuilt-1.3.12 greenkeeper-electron-prebuilt-1.3.13 greenkeeper-electron-prebuilt-1.4.0 greenkeeper-electron-prebuilt-1.4.1 greenkeeper-electron-prebuilt-1.4.2 greenkeeper-electron-prebuilt-1.4.3 greenkeeper-electron-prebuilt-1.4.4 greenkeeper-electron-prebuilt-1.4.5 greenkeeper-electron-prebuilt-1.4.6 greenkeeper-electron-prebuilt-1.4.7 greenkeeper-electron-prebuilt-1.4.8 greenkeeper-electron-prebuilt-1.4.9 greenkeeper-electron-prebuilt-1.4.10 greenkeeper-electron-prebuilt-1.4.11 greenkeeper-electron-prebuilt-1.4.12 greenkeeper-electron-workers-1.8.0 greenkeeper-eslint-2.12.0 greenkeeper-eslint-2.13.0 greenkeeper-eslint-2.13.1 greenkeeper-eslint-3.0.0 greenkeeper-eslint-3.0.1 greenkeeper-eslint-3.1.0 greenkeeper-eslint-3.1.1 greenkeeper-eslint-3.2.0 greenkeeper-eslint-3.2.1 greenkeeper-eslint-3.2.2 greenkeeper-eslint-3.3.0 greenkeeper-eslint-3.3.1 greenkeeper-eslint-3.4.0 greenkeeper-eslint-3.5.0 greenkeeper-eslint-3.6.0 greenkeeper-eslint-3.6.1 greenkeeper-eslint-3.7.0 greenkeeper-eslint-3.7.1 greenkeeper-eslint-3.8.0 greenkeeper-eslint-3.8.1 greenkeeper-eslint-3.9.0 greenkeeper-eslint-3.9.1 greenkeeper-eslint-3.10.0 greenkeeper-eslint-3.10.1 greenkeeper-eslint-3.10.2 greenkeeper-eslint-3.11.0 greenkeeper-eslint-3.11.1 greenkeeper-eslint-3.12.0 greenkeeper-eslint-config-airbnb-base-4.0.0 greenkeeper-eslint-config-airbnb-base-4.0.1 greenkeeper-eslint-config-airbnb-base-4.0.2 greenkeeper-eslint-config-airbnb-base-5.0.0 greenkeeper-eslint-config-airbnb-base-5.0.2 greenkeeper-eslint-config-airbnb-base-5.0.3 greenkeeper-eslint-config-airbnb-base-6.0.0 greenkeeper-eslint-config-airbnb-base-7.0.0 greenkeeper-eslint-config-airbnb-base-7.0.1 greenkeeper-eslint-config-airbnb-base-7.1.0 greenkeeper-eslint-config-airbnb-base-7.2.0 greenkeeper-eslint-config-airbnb-base-8.0.0 greenkeeper-eslint-config-airbnb-base-9.0.0 greenkeeper-eslint-config-airbnb-base-10.0.0 greenkeeper-eslint-config-airbnb-base-10.0.1 greenkeeper-eslint-plugin-import-1.9.2 greenkeeper-eslint-plugin-import-1.10.0 greenkeeper-eslint-plugin-import-1.10.1 greenkeeper-eslint-plugin-import-1.10.2 greenkeeper-eslint-plugin-import-1.10.3 greenkeeper-eslint-plugin-import-1.11.0 greenkeeper-eslint-plugin-import-1.11.1 greenkeeper-eslint-plugin-import-1.12.0 greenkeeper-eslint-plugin-import-1.13.0 greenkeeper-eslint-plugin-import-1.14.0 greenkeeper-eslint-plugin-import-1.15.0 greenkeeper-eslint-plugin-import-1.16.0 greenkeeper-eslint-plugin-import-2.0.0 greenkeeper-eslint-plugin-import-2.0.1 greenkeeper-eslint-plugin-import-2.1.0 greenkeeper-eslint-plugin-import-2.2.0 greenkeeper-lodash.pick-4.3.0 greenkeeper-lodash.pick-4.4.0 greenkeeper-mime-types-2.1.12 greenkeeper-mime-types-2.1.13 greenkeeper-mocha-3.0.0 greenkeeper-mocha-3.0.1 greenkeeper-mocha-3.0.2 greenkeeper-mocha-3.1.0 greenkeeper-mocha-3.1.1 greenkeeper-mocha-3.1.2 greenkeeper-mocha-3.2.0 greenkeeper-npm-run-all-2.1.2 greenkeeper-npm-run-all-2.2.0 greenkeeper-npm-run-all-2.2.1 greenkeeper-npm-run-all-2.2.2 greenkeeper-npm-run-all-2.3.0 greenkeeper-npm-run-all-3.0.0 greenkeeper-npm-run-all-3.1.0 greenkeeper-npm-run-all-3.1.1 greenkeeper-npm-run-all-3.1.2 greenkeeper-pdfjs-dist-1.5.287 greenkeeper-pdfjs-dist-1.5.289 greenkeeper-pdfjs-dist-1.5.292 greenkeeper-pdfjs-dist-1.5.294 greenkeeper-pdfjs-dist-1.5.296 greenkeeper-pdfjs-dist-1.5.299 greenkeeper-pdfjs-dist-1.5.301 greenkeeper-pdfjs-dist-1.5.303 greenkeeper-pdfjs-dist-1.5.305 greenkeeper-pdfjs-dist-1.5.307 greenkeeper-pdfjs-dist-1.5.309 greenkeeper-pdfjs-dist-1.5.311 greenkeeper-pdfjs-dist-1.5.312 greenkeeper-pdfjs-dist-1.5.314 greenkeeper-pdfjs-dist-1.5.316 greenkeeper-pdfjs-dist-1.5.318 greenkeeper-pdfjs-dist-1.5.320 greenkeeper-pdfjs-dist-1.5.322 greenkeeper-pdfjs-dist-1.5.324 greenkeeper-pdfjs-dist-1.5.326 greenkeeper-pdfjs-dist-1.5.328 greenkeeper-pdfjs-dist-1.5.330 greenkeeper-pdfjs-dist-1.5.332 greenkeeper-pdfjs-dist-1.5.334 greenkeeper-pdfjs-dist-1.5.336 greenkeeper-pdfjs-dist-1.5.337 greenkeeper-pdfjs-dist-1.5.339 greenkeeper-pdfjs-dist-1.5.341 greenkeeper-pdfjs-dist-1.5.343 greenkeeper-pdfjs-dist-1.5.345 greenkeeper-pdfjs-dist-1.5.347 greenkeeper-pdfjs-dist-1.5.351 greenkeeper-pdfjs-dist-1.5.353 greenkeeper-pdfjs-dist-1.5.355 greenkeeper-pdfjs-dist-1.5.357 greenkeeper-pdfjs-dist-1.5.359 greenkeeper-pdfjs-dist-1.5.361 greenkeeper-pdfjs-dist-1.5.365 greenkeeper-pdfjs-dist-1.5.367 greenkeeper-pdfjs-dist-1.5.369 greenkeeper-pdfjs-dist-1.5.370 greenkeeper-pdfjs-dist-1.5.372 greenkeeper-pdfjs-dist-1.5.374 greenkeeper-pdfjs-dist-1.5.376 greenkeeper-pdfjs-dist-1.5.378 greenkeeper-pdfjs-dist-1.5.381 greenkeeper-pdfjs-dist-1.5.383 greenkeeper-pdfjs-dist-1.5.385 greenkeeper-pdfjs-dist-1.5.387 greenkeeper-pdfjs-dist-1.5.389 greenkeeper-pdfjs-dist-1.5.391 greenkeeper-pdfjs-dist-1.5.393 greenkeeper-pdfjs-dist-1.5.395 greenkeeper-pdfjs-dist-1.5.397 greenkeeper-pdfjs-dist-1.5.399 greenkeeper-pdfjs-dist-1.5.402 greenkeeper-pdfjs-dist-1.5.404 greenkeeper-pdfjs-dist-1.5.406 greenkeeper-pdfjs-dist-1.5.408 greenkeeper-pdfjs-dist-1.5.410 greenkeeper-pdfjs-dist-1.5.413 greenkeeper-pdfjs-dist-1.5.415 greenkeeper-pdfjs-dist-1.5.418 greenkeeper-pdfjs-dist-1.5.421 greenkeeper-pdfjs-dist-1.5.424 greenkeeper-pdfjs-dist-1.5.426 greenkeeper-pdfjs-dist-1.5.430 greenkeeper-pdfjs-dist-1.5.432 greenkeeper-pdfjs-dist-1.5.434 greenkeeper-pdfjs-dist-1.5.437 greenkeeper-pdfjs-dist-1.5.440 greenkeeper-pdfjs-dist-1.5.442 greenkeeper-pdfjs-dist-1.5.444 greenkeeper-pdfjs-dist-1.5.446 greenkeeper-pdfjs-dist-1.5.448 greenkeeper-pdfjs-dist-1.5.450 greenkeeper-pdfjs-dist-1.5.452 greenkeeper-pdfjs-dist-1.5.454 greenkeeper-pdfjs-dist-1.5.456 greenkeeper-pdfjs-dist-1.5.458 greenkeeper-pdfjs-dist-1.5.460 greenkeeper-pdfjs-dist-1.5.462 greenkeeper-pdfjs-dist-1.5.464 greenkeeper-pdfjs-dist-1.5.466 greenkeeper-pdfjs-dist-1.5.470 greenkeeper-pdfjs-dist-1.5.472 greenkeeper-pdfjs-dist-1.5.474 greenkeeper-pdfjs-dist-1.5.476 greenkeeper-pdfjs-dist-1.5.479 greenkeeper-pdfjs-dist-1.5.488 greenkeeper-pdfjs-dist-1.5.490 greenkeeper-pdfjs-dist-1.5.492 greenkeeper-pdfjs-dist-1.5.494 greenkeeper-pdfjs-dist-1.5.496 greenkeeper-pdfjs-dist-1.5.498 greenkeeper-pdfjs-dist-1.5.500 greenkeeper-pdfjs-dist-1.6.210 greenkeeper-pdfjs-dist-1.6.212 greenkeeper-pdfjs-dist-1.6.214 greenkeeper-pdfjs-dist-1.6.217 greenkeeper-pdfjs-dist-1.6.219 greenkeeper-pdfjs-dist-1.6.221 greenkeeper-pdfjs-dist-1.6.222 greenkeeper-pdfjs-dist-1.6.226 greenkeeper-pdfjs-dist-1.6.230 greenkeeper-pdfjs-dist-1.6.232 greenkeeper-pdfjs-dist-1.6.234 greenkeeper-pdfjs-dist-1.6.237 greenkeeper-pdfjs-dist-1.6.239 greenkeeper-pdfjs-dist-1.6.248 greenkeeper-pdfjs-dist-1.6.250 greenkeeper-pdfjs-dist-1.6.254 greenkeeper-pdfjs-dist-1.6.258 greenkeeper-pdfjs-dist-1.6.263 greenkeeper-pdfjs-dist-1.6.264 greenkeeper-pdfjs-dist-1.6.266 greenkeeper-pdfjs-dist-1.6.268 greenkeeper-pdfjs-dist-1.6.271 greenkeeper-pdfjs-dist-1.6.272 greenkeeper-pdfjs-dist-1.6.274 greenkeeper-pdfjs-dist-1.6.279 greenkeeper-pdfjs-dist-1.6.283 greenkeeper-pdfjs-dist-1.6.284 greenkeeper-pdfjs-dist-1.6.287 greenkeeper-pdfjs-dist-1.6.289 greenkeeper-pdfjs-dist-1.6.293 greenkeeper-pdfjs-dist-1.6.295 greenkeeper-pdfjs-dist-1.6.297 greenkeeper-pdfjs-dist-1.6.299 greenkeeper-pdfjs-dist-1.6.302 greenkeeper-pdfjs-dist-1.6.304 greenkeeper-pdfjs-dist-1.6.306 greenkeeper-pdfjs-dist-1.6.309 greenkeeper-pdfjs-dist-1.6.313 greenkeeper-pdfjs-dist-1.6.315 greenkeeper-pdfjs-dist-1.6.317 greenkeeper-pdfjs-dist-1.6.319 greenkeeper-pdfjs-dist-1.6.320 greenkeeper-pdfjs-dist-1.6.322 greenkeeper-pdfjs-dist-1.6.324 greenkeeper-pdfjs-dist-1.6.327 greenkeeper-pdfjs-dist-1.6.329 greenkeeper-pdfjs-dist-1.6.331 greenkeeper-pdfjs-dist-1.6.332 greenkeeper-pdfjs-dist-1.6.334 greenkeeper-pdfjs-dist-1.6.336 greenkeeper-pdfjs-dist-1.6.338 greenkeeper-pdfjs-dist-1.6.341 greenkeeper-pdfjs-dist-1.6.343 greenkeeper-pdfjs-dist-1.6.346 greenkeeper-pdfjs-dist-1.6.348 greenkeeper-pdfjs-dist-1.6.350 greenkeeper-pdfjs-dist-1.6.351 greenkeeper-pdfjs-dist-1.6.353 greenkeeper-pdfjs-dist-1.6.355 greenkeeper-pdfjs-dist-1.6.357 greenkeeper-pdfjs-dist-1.6.359 greenkeeper-pdfjs-dist-1.6.361 greenkeeper-pdfjs-dist-1.6.365 greenkeeper-pdfjs-dist-1.6.366 greenkeeper-pdfjs-dist-1.6.370 greenkeeper-pdfjs-dist-1.6.372 greenkeeper-pdfjs-dist-1.6.374 greenkeeper-pdfjs-dist-1.6.377 greenkeeper/remove-node-0.10 greenkeeper/update-all master
Nothing to show
Clone or download
Latest commit ed465df Jun 28, 2017

README.md

electron-html-to

NPM VersionLicenseBuild Status

Highly scalable html conversion in scale

This module let you convert a web page (html, css, js) in any format you want (via a converter function) using electron.

Works in electron@>=0.36.1 including electron@1

var fs = require('fs'),
    convertFactory = require('electron-html-to');

var conversion = convertFactory({
  converterPath: convertFactory.converters.PDF
});

conversion({ html: '<h1>Hello World</h1>' }, function(err, result) {
  if (err) {
    return console.error(err);
  }

  console.log(result.numberOfPages);
  console.log(result.logs);
  result.stream.pipe(fs.createWriteStream('/path/to/anywhere.pdf'));
  conversion.kill(); // necessary if you use the electron-server strategy, see bellow for details
});

Built-in converters

  • convertFactory.converters.PDF (html to pdf) -> when the conversion ends the result param will have numberOfPages (Number) and stream (Stream) properties.

Custom converters

Converters are functions that run in the electron process, see the pdf conversion implementation for an example.

Global options

var conversion = require('electron-html-to')({
  /* optional absolute path to a custom electron executable, if not passed we will try to detect the path of the electron executable installed */
  pathToElectron: '/path/to/custom/electron-executable',
  /* optional array of custom arguments to pass to the electron executable */
  electronArgs: ['--some-value=2', '--enable-some-behaviour'],
  /* required absolute path to the converter function to use, every conversion will use the converter specified  */
  converterPath: '/path/to/a/converter.js'
  /* number of allocated electron processes (when using electron-server strategy). defaults to 2 */
  numberOfWorkers: 2,
  /* time in ms to wait for worker ping response in order to be considered alive when using `electron-server` or `electron-ipc` strategy, see https://github.com/bjrmatos/electron-workers#options for details */
  pingTimeout: 100,
  /* timeout in ms for html conversion, when the timeout is reached, the conversion is cancelled. defaults to 180000ms */
  timeout: 5000,
  /* directory where are stored temporary html and pdf files, use something like npm package reap to clean this up */
  tmpDir: 'os/tmpdir',
  /* optional port range where to start electron server (when using electron-server strategy) */
  portLeftBoundary: 1000,
  portRightBoundary: 2000,
  /* optional hostname where to start electron server when using electron-server strategy) */
  host: '127.0.0.1',
  /* set to true to allow request using the file protocol (file:///). defaults to false */
  allowLocalFilesAccess: false,
  /* the collected console.log, console.error, console.warn messages are trimmed by default */
  maxLogEntrySize: 1000,
  /* optional chrome command line switches, see http://electron.atom.io/docs/v0.36.1/api/chrome-command-line-switches/ for details. defaults to { 'ignore-certificate-errors': null } */
  chromeCommandLineSwitches: {
    'disable-http-cache': null,
    'log-net-log': '/path/to/save'
  },
  /* use rather dedicated process for every conversion,
    dedicated-process strategy is quite slower but can solve some bugs
    with corporate proxy. for a description of `electron-server` and `electron-ipc` strategy see [electron-workers docs](https://github.com/bjrmatos/electron-workers/#modes). defaults to electron-ipc strategy */
  strategy: 'electron-ipc | electron-server | dedicated-process'
});

Local options

conversion({
  html: '<h1>Hello world</h1>',
  url: 'http://jsreport.net', // set direct url instead of html
  delay: 0, // time in ms to wait before the conversion
  // boolean that specifies if we should collect logs calls (console.log, console.error, console.warn) in webpage
  // logs will be available as result.logs after the conversion
  // defaults to true
  collectLogs: true,
  waitForJS: true, // set to true to enable programmatically specify (via Javascript of the page) when the conversion starts (see Programmatic conversion section for an example)
  waitForJSVarName: 'MY_CUSTOM_VAR_NAME', // name of the variable that will be used as the conversion trigger, defaults to "ELECTRON_HTML_TO_READY" (see Programmatic pdf printing section for an example)
  userAgent: 'CUSTOM_USER_AGENT', // set a custom user agent to use in electron's browser window
  /* custom extra headers to load the html or url */
  extraHeaders: {
    'X-Foo': 'foo',
    'X-Bar': 'bar'
  },
  converterPath: '/path/to/a/converter.js', // absolute path to the converter function to use in the local conversion, if no specified the global converterPath option will be used

  // options for electron's browser window, see http://electron.atom.io/docs/v0.36.1/api/browser-window/ for details for each option.
  // allowed browser-window options
  browserWindow: {
    width: 600, // defaults to 600
    height: 600, // defaults to 600
    x: 0,
    y: 0,
    useContentSize: false,
    webPreferences: {
      nodeIntegration: false, // defaults to false
      partition: '',
      zoomFactor: 3.0,
      javascript: true, // defaults to true
      webSecurity: false, // defaults to false
      allowDisplayingInsecureContent: true,
      allowRunningInsecureContent: true,
      images: true,
      java: true,
      webgl: true,
      webaudio: true,
      plugins: ,
      experimentalFeatures: ,
      experimentalCanvasFeatures: ,
      overlayScrollbars: ,
      overlayFullscreenVideo: ,
      sharedWorker: ,
      directWrite:
    }
  },

  // options to the pdf converter function, see electron's printoToPDF function http://electron.atom.io/docs/v0.36.1/api/web-contents/#webcontents-printtopdf-options-callback for details for each option.
  // allowed printToPDF options
  pdf: {
    marginsType: 0,
    pageSize: 'A4',
    printBackground: false,
    landscape: false
  }
}, cb);

Local resources

You can add local files like .css, .jpg or .js files by setting the allowLocalFilesAccess option to true. This option allow requests with the file protocol file:///.

Example:

<!-- index.html -->
<head>
	<link rel="stylesheet" href="/css/pdf.css">
</head>
<body>
	<h1 class="title">It Works!!</h1>
	<img src="/images/company_logo.jpg" title="MyLogo">
</body>

If your html doesn't have url in the form of file://path/to/you/base/public/directory you would need to transform paths from /images/company_logo.jpg to file://path/to/you/base/public/directory/images/company_logo.jpg.

const fs = require('fs');
const convertFactory = require('electron-html-to');
fs.readFile('index.html', 'utf8', (err, htmlString) => {
  // add local path in case your HTML has relative paths
  htmlString = htmlString.replace(/href="|src="/g, match => {
    return match + 'file://path/to/you/base/public/directory';
  });
  const conversion = convertFactory({
    converterPath: convertFactory.converters.PDF,
    allowLocalFilesAccess: true
  });
  conversion({ html: htmlString }, (err, result) => {
    if (err) return console.error(err);
    result.stream.pipe(fs.createWriteStream('/path/to/anywhere.pdf'));
    conversion.kill(); // necessary if you use the electron-server strategy, see bellow for details
  });
});

Kill workers

// kill all electron workers when using electron-server strategy
conversion.kill();

Programmatic conversion

If you need to programmatic trigger the conversion process (because you need to calculate some values or do something async in your page before convert it) you can enable the waitForJS local option, when waitForJS is set to true the conversion will wait until you set a variable to true in your page, by default the name of the variable is ELECTRON_HTML_TO_READY but you can customize it via waitForJSVarName option.

Example

local options:

conversion({
  html: '<custom html here>',
  waitForJS: true
}, cb);

custom html:

<h1></h1>
<script>
  // do some calculations or something async
  setTimeout(function() {
    window.ELECTRON_HTML_TO_READY = true; // this will start the conversion
  }, 500);
</script>

Debugging

  • To get more information (internal debugging logs of the module) about what's happening inside the conversion run your app with the DEBUG env var: DEBUG=electron-html-to,electron-html-to:* node app.js (on Windows use set DEBUG=electron-html-to,electron-html-to:* && node app.js). This will print out some additional information about what's going on.

  • To see the electron process UI created (the visible electron window) and point stdout/stderr of the electron processes to console run your app with the ELECTRON_HTML_TO_DEBUGGING env var: ELECTRON_HTML_TO_DEBUGGING=true node app.js (on Windows use set ELECTRON_HTML_TO_DEBUGGING=true && node app.js).

  • To only point stdout/stderr of the electron processes to console run your app with the ELECTRON_HTML_TO_STDSTREAMS env var: ELECTRON_HTML_TO_STDSTREAMS=true node app.js (on Windows use set ELECTRON_HTML_TO_STDSTREAMS=true && node app.js).

  • To enable low level messages (chromium logs) of the electron processes run your app with the ELECTRON_ENABLE_LOGGING env var: ELECTRON_ENABLE_LOGGING=true node app.js (on Windows use set ELECTRON_ENABLE_LOGGING=true && node app.js).

Requirements

  • Install electron >= 0.36.1 including electron@1, the easy way to install electron in your app is npm install electron --save or npm install electron-prebuilt --save

Troubleshooting

Using electron in single core machines

If you are using a machine with a single-core processor you will probably experience a high CPU usage when doing any conversion (97% in most cases and the usage is worse when using Windows), this is because a limitation in electron when it is being used on single core machines, unfortunately the only way to overcome this is to upgrade your machine to a processor with more cores (a processor with two cores is fine). more info: issue1, issue2

env: node: No such file or directory when using electron-prebuilt and nvm

If you are using node with nvm and you have installed electron with npm install -g electron-prebuilt you probably will see an error or log with env: node: No such file or directory, this is because the electron executable installed by electron-prebuilt is a node CLI spawning the real electron executable internally, since nvm don't install/symlink node to /usr/bin/env/node when the electron executable installed by electron-prebuilt tries to run, it will fail because node won't be found in that context..

Solution:

1.- Install electron-prebuilt as a dependency in your app, this is the option recommended because you probably want to ensure your app always run with the exact version you tested it, and probably you don't want to install electron globally in your system.

2.- You can make a symlink to /usr/bin/env/node but this is not recommended by nvm authors, because you will loose all the power that nvm brings.

3.- Put the path to the real electron executable in your $PATH.

License

See license