From 080c9c0da9365a81eb932243e34360ca613d97d5 Mon Sep 17 00:00:00 2001 From: Mike Petrovich Date: Thu, 8 Oct 2015 22:46:32 -0400 Subject: [PATCH] Manually inline external scripts instead of executing them via jsdom jsdom does not implement layout-specific functionality like offsetWidth() or getBoundingClientRect() (see https://github.com/tmpvar/jsdom/issues/653, https://github.com/tmpvar/jsdom/issues/135). The good news is that jsdom doesn't need to be used at all. Instead, the HTML file can be imported directly, and any external scripts or stylesheets can be inlined as well. PhantomJS will render the resulting HTML without issue, since it's using WebKit behind the scenes. --- imagely.js | 85 ++++++++++++++++++++++++++-------------------------- package.json | 1 - 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/imagely.js b/imagely.js index 685d159..fbcf3cf 100644 --- a/imagely.js +++ b/imagely.js @@ -1,5 +1,4 @@ var fs = require('fs'); -var jsdom = require('jsdom'); var imageSize = require('image-size'); var path = require('path'); var phantom = require('phantom'); @@ -36,6 +35,11 @@ function imagely(source, destination, options, callback) { } } +/** + * Generates an image from a URL for an HTML file. + * + * @private + */ function renderUrl(url, destination, options, callback) { phantom.create(function(phantomjs) { phantomjs.createPage(function(page) { @@ -52,56 +56,51 @@ function renderUrl(url, destination, options, callback) { } /** - * Generates an image from a local file. + * Generates an image from a local HTML file. * * @private + * @todo Add support for remote scripts and stylesheets */ function renderFile(filepath, destination, options, callback) { - jsdom.env({ - file: filepath, - features: { - FetchExternalResources: ['link', 'script'], - ProcessExternalResources: ['script'], - }, - created: function(err, window) { - if (err) { - console.error('imagely: Error while creating window', err); - return; - } - - if (options.json) { - var json = fs.readFileSync(options.json, 'utf-8'); - window.data = JSON.parse(json); - } - }, - done: function(err, window) { - if (err) { - console.error('imagely: Error while loading document', err); - return; - } - - var html = window.document.documentElement.outerHTML; - - // Removes scripts since they have already been processed - html = html.replace(/'; + }); + + // Inlines stylesheets + html = html.replace(/(]*href="([^"]+.css)"[^>]*>)/gi, function(subject, linkTag, cssFile) { + if (isUrl(cssFile)) { + // Skips remote stylesheets + return linkTag; + } - phantom.create(function(phantomjs) { - phantomjs.createPage(function(page) { - page.setContent(html); - renderPage(page, phantomjs, destination, options, callback); - }); - }, { binary: phantomjs.path }); - }, + var cssFilepath = path.resolve(path.dirname(filepath), cssFile); + var css = fs.readFileSync(cssFilepath, 'utf-8'); + return ''; }); + + phantom.create(function(phantomjs) { + phantomjs.createPage(function(page) { + page.setContent(html); + renderPage(page, phantomjs, destination, options, callback); + }); + }, { binary: phantomjs.path }); } +/** + * Generates an image from a populated PhantomJS page. + * + * @private + */ function renderPage(page, phantomjs, destination, options, callback) { if (options.width || options.height) { page.set('viewportSize', { width: options.width, height: options.height }); diff --git a/package.json b/package.json index f431a68..a2d8ee5 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ }, "dependencies": { "image-size": "^0.3.5", - "jsdom": "^3.1.2", "phantom": "^0.8.0", "phantomjs": "^1.9.18", "yargs": "^3.26.0"