Skip to content

Commit

Permalink
Manually inline external scripts instead of executing them via jsdom
Browse files Browse the repository at this point in the history
jsdom does not implement layout-specific functionality like offsetWidth() or getBoundingClientRect() (see jsdom/jsdom#653, jsdom/jsdom#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.
  • Loading branch information
mpetrovich committed Oct 9, 2015
1 parent ea01b01 commit 080c9c0
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 44 deletions.
85 changes: 42 additions & 43 deletions 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');
Expand Down Expand Up @@ -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) {
Expand All @@ -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(/<script .*?<\/script>/gi, '');

// Inlines external stylesheets
html = html.replace(/(<link [^>]*href="([^"]+.css)"[^>]*>)/gi, function(subject, linkTag, cssFile) {
var cssFilepath = path.resolve(path.dirname(filepath), cssFile);
var css = fs.readFileSync(cssFilepath, 'utf-8');
return '<style>' + css + '</style>';
});
var html = fs.readFileSync(filepath, 'utf-8');

// Inlines scripts
html = html.replace(/(<script [^>]*src="([^"]+.js)"[^>]*>)/gi, function(subject, scriptTag, jsFile) {
if (isUrl(jsFile)) {
// Skips remote scripts
return scriptTag;
}

var jsFilepath = path.resolve(path.dirname(filepath), jsFile);
var js = fs.readFileSync(jsFilepath, 'utf-8');
return '<script>' + js + '</script>';
});

// Inlines stylesheets
html = html.replace(/(<link [^>]*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 '<style>' + css + '</style>';
});

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 });
Expand Down
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -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"
Expand Down

0 comments on commit 080c9c0

Please sign in to comment.