Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

amperize

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

amperize - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

109

lib/amperize.js

@@ -12,2 +12,3 @@ 'use strict';

, http = require('http')
, https = require('https')
, sizeOf = require('image-size')

@@ -18,3 +19,11 @@ , helpers = require('./helpers');

img: {
layout: 'responsive'
layout: 'responsive',
width: 600,
height: 400,
},
iframe: {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}

@@ -117,27 +126,93 @@ };

/**
* Get the image sizes (width and heigth plus type of image)
*
* https://github.com/image-size/image-size
*
* @param {Object} element
* @return {Object} element incl. width and height
*/
function getImageSize(element) {
var options = url.parse(element.attribs.src);
var request = element.attribs.src.indexOf('https') === 0 ? https : http;
// 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 enter();
} catch (err) {
// fallback to default values, so the HTML get validated at least
element.attribs.width = amperize.config.img.width;
element.attribs.height = amperize.config.img.height;
return enter();
}
});
}).on('error', function () {
// fallback to default values, so the HTML get validated at least
element.attribs.width = amperize.config.img.width;
element.attribs.height = amperize.config.img.height;
return enter();
});
}
if ((element.name === 'img' || element.name === 'iframe') && !element.attribs.src) {
return enter();
}
if (element.name === 'img' && amperize.config.img) {
element.name = 'amp-img';
// when we have a gif it should be <amp-anim>.
element.name = element.attribs.src.match(/(\.gif$)/) ? 'amp-anim' : 'amp-img';
if (!element.attribs.layout) {
element.attribs.layout = amperize.config.img.layout;
if (!element.attribs.width || !element.attribs.height || !element.attribs.layout) {
element.attribs.layout = !element.attribs.layout ? amperize.config.iframe.layout : element.attribs.layout;
if (element.attribs.src.indexOf('http') === 0) {
return getImageSize(element);
} else {
element.attribs.width = amperize.config.img.width;
element.attribs.height = amperize.config.img.height;
}
}
}
if ((!element.attribs.width || !element.attribs.height) && element.attribs.src.indexOf('http') === 0) {
var options = url.parse(element.attribs.src);
if (element.name ==='iframe') {
element.name = 'amp-iframe';
return http.get(options, function (response) {
var chunks = [];
if (!element.attribs.width || !element.attribs.height || !element.attribs.layout) {
response.on('data', function (chunk) {
chunks.push(chunk);
}).on('end', function () {
var dimensions = sizeOf(Buffer.concat(chunks));
element.attribs.width = dimensions.width;
element.attribs.height = dimensions.height;
return enter();
});
});
element.attribs.layout = !element.attribs.layout ? amperize.config.iframe.layout : element.attribs.layout;
element.attribs.width = !element.attribs.width ? amperize.config.iframe.width : element.attribs.width;
element.attribs.height = !element.attribs.height ? amperize.config.iframe.height : element.attribs.height;
element.attribs.sandbox = !element.attribs.sandbox ? amperize.config.iframe.sandbox : element.attribs.sandbox;
}
}
if (element.name === 'audio') {
element.name = 'amp-audio';
}
if (element.attribs && element.attribs.src) {
// Every src attribute must be with 'https' protocol otherwise it will not get validated by AMP.
// If we're unable to replace it, we will deal with the valitation error, but at least
// we tried.
if (element.attribs.src.indexOf('https://') === -1) {
if (element.attribs.src.indexOf('http://') === 0) {
// Replace 'http' with 'https', so the validation passes
element.attribs.src = element.attribs.src.replace(/^http:\/\//i, 'https://');
} else if (element.attribs.src.indexOf('//') === 0) {
// Giphy embedded iFrames are without protocol and start with '//', so at least
// we can fix those cases.
element.attribs.src = 'https:' + element.attribs.src;
}
}
}
return enter();

@@ -144,0 +219,0 @@ }, done);

3

lib/helpers.js

@@ -9,3 +9,4 @@ 'use strict';

'area', 'base', 'br', 'col', 'command', 'embed', 'hr',
'img', 'input', 'link', 'meta', 'param', 'source', 'wbr'
'img', 'input', 'link', 'meta', 'param', 'source', 'wbr',
'track'
];

@@ -12,0 +13,0 @@

{
"name": "amperize",
"version": "0.2.0",
"version": "0.3.0",
"description": "AMP up your plain HTML",

@@ -10,7 +10,8 @@ "main": "./lib/amperize",

"coverage": "istanbul cover ./node_modules/.bin/_mocha -- $(find test -name '*.test.js')",
"test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- $(find test -name '*.test.js')"
"test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- $(find test -name '*.test.js')",
"semantic-release": "semantic-release pre && npm publish && semantic-release post"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jbhannah/amperize.git"
"url": "https://github.com/jbhannah/amperize.git"
},

@@ -28,16 +29,25 @@ "keywords": [

"dependencies": {
"async": "1.4.2",
"async": "2.0.1",
"emits": "3.0.0",
"htmlparser2": "3.8.3",
"image-size": "0.3.5",
"lodash.merge": "3.3.2",
"node-uuid": "1.4.3"
"htmlparser2": "3.9.1",
"image-size": "0.5.0",
"lodash.merge": "4.6.0",
"nock": "^8.0.0",
"node-uuid": "1.4.7",
"rewire": "^2.5.2"
},
"devDependencies": {
"chai": "3.4.0",
"istanbul": "0.4.0",
"mocha": "2.3.3",
"sinon": "1.17.2",
"chai": "3.5.0",
"cz-conventional-changelog": "1.2.0",
"istanbul": "0.4.4",
"mocha": "3.0.2",
"semantic-release": "4.3.5",
"sinon": "1.17.5",
"sinon-chai": "2.8.0"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}

@@ -7,3 +7,5 @@ 'use strict';

, sinonChai = require('sinon-chai')
, Amperize = require('../lib/amperize')
, nock = require('nock')
, rewire = require('rewire')
, Amperize = rewire('../lib/amperize')
, amperize;

@@ -31,5 +33,13 @@

expect(amperize.config).to.be.eql({
img: {
layout: 'responsive'
}
img: {
layout: 'responsive',
width: 600,
height: 400,
},
iframe: {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}
});

@@ -61,2 +71,14 @@ });

describe('#parse', function () {
var sizeOfMock,
sizeOfStub;
beforeEach(function () {
// stubbing the `image-size` lib, so we don't to a request everytime
sizeOfStub = sinon.stub();
});
afterEach(function () {
sinon.restore();
});
it('throws an error if no callback provided', function () {

@@ -70,7 +92,189 @@ function err() {

it('transforms <img> into <amp-img></amp-img>', function () {
amperize.parse('<img src="http://lorempixel.com/output/abstract-q-c-640-480-3.jpg">', function (error, result) {
expect(result).to.be.equal('<amp-img src="http://lorempixel.com/output/abstract-q-c-640-480-3.jpg" layout="responsive" width="640" height="480"></amp-img>');
it('transforms <img> with layout property into <amp-img></amp-img> without overriding it and full image dimensions', function (done) {
sizeOfMock = nock('http://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
.reply(200, {
data: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
});
sizeOfStub.returns({width: 50, height: 50, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256" layout="FIXED">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256"');
expect(result).to.contain('layout="FIXED"');
expect(result).to.contain('width="50"');
expect(result).to.contain('height="50"');
expect(result).to.contain('</amp-img>');
done();
});
});
it('transforms .gif <img> with only height property into <amp-anim></amp-anim> with full dimensions by overriding them', function (done) {
sizeOfMock = nock('https://media.giphy.com')
.get('/media/l46CtzgjhTm29Cbjq/giphy.gif')
.reply(200, {
data: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
});
sizeOfStub.returns({width: 800, height: 600, type: 'gif'});
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="https://media.giphy.com/media/l46CtzgjhTm29Cbjq/giphy.gif" height="500">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-anim');
expect(result).to.contain('src="https://media.giphy.com/media/l46CtzgjhTm29Cbjq/giphy.gif"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="800"');
expect(result).to.contain('height="600"');
expect(result).to.contain('</amp-anim>');
done();
});
});
it('transforms <iframe> with only width property into <amp-iframe></amp-iframe> with full dimensions withour overriding them', function (done) {
amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" width="400"></iframe>', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-iframe');
expect(result).to.contain('src="https://www.youtube.com/embed/HMQkV5cTuoY"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="400"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts allow-same-origin"')
done();
});
});
it('adds \'https\' protocol to <iframe> if no protocol is supplied (e. e. giphy)', function (done) {
var url = '<iframe src="//giphy.com/embed/3oEduKP4VaUxJvLwuA" width="480" height="372" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>';
amperize.parse(url, function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-iframe');
expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="480"');
expect(result).to.contain('height="372"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts allow-same-origin"')
done();
});
});
it('adds \'https\' protocol to <iframe> if only \'http\' protocol is supplied', function (done) {
var url = '<iframe src="http://giphy.com/embed/3oEduKP4VaUxJvLwuA" width="480" height="372" frameBorder="0" class="giphy-embed" allowFullScreen></iframe><p><a href="http://giphy.com/gifs/afv-funny-fail-lol-3oEduKP4VaUxJvLwuA">via GIPHY</a></p></p>';
amperize.parse(url, function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-iframe');
expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="480"');
expect(result).to.contain('height="372"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts allow-same-origin"')
done();
});
});
it('transforms local <img> into <amp-img></amp-img> with default image dimensions', function (done) {
amperize.parse('<img src="/content/images/IMG_xyz.jpg">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="/content/images/IMG_xyz.jpg"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-img>');
done();
});
});
it('can handle <img> tag without src and does not transform it', function (done) {
amperize.parse('<img><//img><p>some text here</p>', function (error, result) {
expect(result).to.exist;
expect(result).to.be.equal('<img><p>some text here</p>');
done();
});
});
it('can handle <iframe> tag without src and does not transform it', function (done) {
amperize.parse('<iframe>', function (error, result) {
expect(result).to.exist;
expect(result).to.be.equal('<iframe></iframe>');
done();
});
});
it('transforms <audio> with a fallback to <amp-audio>', function (done) {
amperize.parse('<audio src="http://foo.mp3" autoplay>Your browser does not support the <code>audio</code> element.</audio>', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-audio src="https://foo.mp3" autoplay="">');
expect(result).to.contain('Your browser does not support the <code>audio</code> element.');
expect(result).to.contain('</amp-audio>');
done();
});
});
it('transforms <audio> with a <source> tag to <amp-audio> and maintains the attributes', function (done) {
amperize.parse('<audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="//foo.wav" type="audio/wav"></audio>', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-audio');
expect(result).to.contain('controls="controls" width="auto" height="50" autoplay="mobile"');
expect(result).to.contain('<source src="https://foo.wav" type="audio/wav">');
expect(result).to.contain('</amp-audio>');
done();
});
});
it('transforms <audio> with a <track> tag to <amp-audio>', function (done) {
amperize.parse('<audio src="foo.ogg"><track kind="captions" src="https://foo.en.vtt" srclang="en" label="English"><track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska"></audio>', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-audio src="foo.ogg">');
expect(result).to.contain('<track kind="captions" src="https://foo.en.vtt" srclang="en" label="English">');
expect(result).to.contain('<track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska">');
expect(result).to.contain('</amp-audio>');
done();
});
});
it('can handle request errors by falling back to the default values defined in config', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.replyWithError('something awful happened');
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://example.com/images/IMG_xyz.jpg"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-img>');
done();
});
});
it('can handle errors of image-size module by falling back to the default values defined in config', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.reply(200, {
data: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
});
sizeOfStub.throws('Not found');
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://example.com/images/IMG_xyz.jpg"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-img>');
done();
});
});
});

@@ -77,0 +281,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc