diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/lib/.DS_Store differ diff --git a/lib/amperize.js b/lib/amperize.js index 1651831..0e0ba29 100644 --- a/lib/amperize.js +++ b/lib/amperize.js @@ -8,9 +8,9 @@ var merge = require('lodash.merge') , uuid = require('uuid') , async = require('async') , url = require('url') - , http = require('http') - , https = require('https') + , got = require('got') , sizeOf = require('image-size') + , validator = require('validator') , helpers = require('./helpers'); var DEFAULTS = { @@ -170,52 +170,66 @@ Amperize.prototype.traverse = function traverse(data, html, done) { * @return {Object} element incl. width and height */ function getImageSize(element) { - var options = url.parse(element.attribs.src), - timeout = 5000, - request = element.attribs.src.indexOf('https') === 0 ? https : http; + var imagePath = url.parse(element.attribs.src), + requestOptions, + timeout = 5000; called = false; + if (!validator.isURL(imagePath.href)) { + if (called) return; + called = true; + + // revert this element, do not show + element.name = 'img'; + + return enter(); + } + // We need the user-agent, otherwise some https request may fail (e. g. cloudfare) - options.headers = { 'User-Agent': 'Mozilla/5.0' }; - - return request.get(options, function (response) { - var chunks = []; - response.on('data', function (chunk) { - chunks.push(chunk); - }).on('end', function () { - try { - var dimensions = sizeOf(Buffer.concat(chunks)); - element.attribs.width = dimensions.width; - element.attribs.height = dimensions.height; - - return getLayoutAttribute(element); - } catch (err) { - if (called) return; - called = true; - - // revert this element, do not show - element.name = 'img'; - return enter(); + requestOptions = { + headers: { + 'User-Agent': 'Mozilla/5.0' + }, + timeout: timeout, + encoding: null + }; + + return got ( + imagePath.href, + requestOptions + ).then(function (response) { + try { + // Using the Buffer rather than an URL requires to use sizeOf synchronously. + // See https://github.com/image-size/image-size#asynchronous + var dimensions = sizeOf(response.body); + + // CASE: `.ico` files might have multiple images and therefore multiple sizes. + // We return the largest size found (image-size default is the first size found) + if (dimensions.images) { + dimensions.width = _.maxBy(dimensions.images, function (w) {return w.width;}).width; + dimensions.height = _.maxBy(dimensions.images, function (h) {return h.height;}).height; } - }); - }).on('socket', function (socket) { - socket.setTimeout(timeout); - socket.on('timeout', function () { + + element.attribs.width = dimensions.width; + element.attribs.height = dimensions.height; + + return getLayoutAttribute(element); + } catch (err) { if (called) return; called = true; // revert this element, do not show element.name = 'img'; return enter(); - }); - }).on('error', function () { - if (called) return; - called = true; - - // revert this element, do not show - element.name = 'img'; - return enter(); + } + }).catch(function (err) { + if (called) return; + called = true; + + // revert this element, do not show + element.name = 'img'; + return enter(); }); } diff --git a/package.json b/package.json index 819e970..ec04513 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,14 @@ "dependencies": { "async": "2.1.4", "emits": "3.0.0", + "got": "7.1.0", "htmlparser2": "3.9.2", "image-size": "0.5.1", "lodash.merge": "4.6.0", "nock": "^9.0.2", "rewire": "^2.5.2", - "uuid": "^3.0.0" + "uuid": "^3.0.0", + "validator": "8.2.0" }, "devDependencies": { "chai": "3.5.0", diff --git a/test/amperize.test.js b/test/amperize.test.js index b50cb63..a408759 100644 --- a/test/amperize.test.js +++ b/test/amperize.test.js @@ -81,6 +81,7 @@ describe('Amperize', function () { afterEach(function () { sinon.restore(); + Amperize.__set__('called', false); }); it('throws an error if no callback provided', function () { @@ -95,7 +96,7 @@ describe('Amperize', function () { sizeOfMock = nock('http://static.wixstatic.com') .get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256') .reply(200, { - data: '' + body: '' }); sizeOfStub.returns({width: 50, height: 50, type: 'jpg'}); @@ -118,7 +119,7 @@ describe('Amperize', function () { sizeOfMock = nock('http://static.wixstatic.com') .get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256') .reply(200, { - data: '' + body: '' }); sizeOfStub.returns({width: 350, height: 200, type: 'jpg'}); @@ -141,7 +142,7 @@ describe('Amperize', function () { sizeOfMock = nock('https://media.giphy.com') .get('/media/l46CtzgjhTm29Cbjq/giphy.gif') .reply(200, { - data: '' + body: '' }); sizeOfStub.returns({width: 800, height: 600, type: 'gif'}); @@ -230,6 +231,15 @@ describe('Amperize', function () { }); }); + it('can handle invalid URLs', function (done) { + amperize.parse('', function (error, result) { + expect(result).to.exist; + expect(Amperize.__get__('called')).to.be.equal(true); + expect(result).to.be.equal(''); + done(); + }); + }); + it('can handle