Socket
Socket
Sign inDemoInstall

amperize

Package Overview
Dependencies
37
Maintainers
3
Versions
22
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.5 to 0.3.6

.eslintrc.json

410

lib/amperize.js
'use strict';
var EventEmitter = require('events').EventEmitter
, emits = require('emits')
, html = require('htmlparser2')
, util = require('util')
, uuid = require('uuid')
, async = require('async')
, url = require('url')
, got = require('got')
, _ = require('lodash')
, sizeOf = require('image-size')
, validator = require('validator')
, helpers = require('./helpers');
var EventEmitter = require('events').EventEmitter,
emits = require('emits'),
html = require('htmlparser2'),
util = require('util'),
uuid = require('uuid'),
async = require('async'),
url = require('url'),
got = require('got'),
_ = require('lodash'),
sizeOf = require('image-size'),
validator = require('validator'),
helpers = require('./helpers'),
DEFAULTS = {
'amp-img': {
layout: 'responsive',
width: 600,
height: 400
},
'amp-anim': {
layout: 'responsive',
width: 600,
height: 400
},
'amp-iframe': {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}
};
var DEFAULTS = {
'amp-img': {
layout: 'responsive',
width: 600,
height: 400,
},
'amp-anim': {
layout: 'responsive',
width: 600,
height: 400,
},
'amp-iframe': {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}
};
/**
* Amperizer constructor. Borrows from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L15
*
* @constructor
* @param {Object} options Options object
* @api public
*/
* Amperizer constructor. Borrows from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L15
*
* @constructor
* @param {Object} options Options object
* @api public
*/
function Amperize(options) {
this.config = _.merge({}, DEFAULTS, options || {});
this.emits = emits;
this.config = _.merge({}, DEFAULTS, options || {});
this.emits = emits;
this.htmlParser = new html.Parser(
new html.DomHandler(this.emits('read'))
);
this.htmlParser = new html.Parser(
new html.DomHandler(this.emits('read'))
);
}

@@ -56,205 +55,212 @@

/**
* Parse the content and call the callback. Borrowed from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L51
*
* @param {String} content HTML
* @param {Function} callback
* @api public
*/
* Parse the content and call the callback. Borrowed from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L51
*
* @param {String} content HTML
* @param {Function} callback
* @api public
*/
Amperize.prototype.parse = function parse(content, callback) {
if (typeof callback !== 'function') throw new Error('No callback provided');
var id = uuid.v4();
var id;
this.once('read', this.amperizer.bind(this, id));
this.once('parsed: ' + id, callback);
if (typeof callback !== 'function') {
throw new Error('No callback provided');
}
this.htmlParser.parseComplete(content);
id = uuid.v4();
this.once('read', this.amperizer.bind(this, id));
this.once('parsed: ' + id, callback);
this.htmlParser.parseComplete(content);
};
/**
* Turn a traversible DOM into string content. Borrowed from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L74
*
* @param {Object} error
* @param {Object} dom Traversible DOM object
* @api private
*/
* Turn a traversible DOM into string content. Borrowed from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L74
*
* @param {String} id
* @param {Object} error
* @param {Object} dom Traversible DOM object
* @api private
*/
Amperize.prototype.amperizer = function amperizer(id, error, dom) {
if (error) throw new Error('Amperizer failed to parse DOM', error);
if (error) {
throw new Error('Amperizer failed to parse DOM', error);
}
this.traverse(dom, '', this.emits('parsed: ' + id));
this.traverse(dom, '', this.emits('parsed: ' + id));
};
/**
* Reduce the traversible DOM object to a string. Borrows from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L90
*
* @param {Array} data
* @param {String} html Compiled HTML contents
* @param {Function} done Callback function
* @api private
*/
* Reduce the traversible DOM object to a string. Borrows from Minimize.
*
* https://github.com/Swaagie/minimize/blob/4b815e274a424ca89551d28c4e0dd8b06d9bbdc2/lib/minimize.js#L90
*
* @param {Array} data
* @param {String} html Compiled HTML contents
* @param {Function} done Callback function
* @api private
*/
Amperize.prototype.traverse = function traverse(data, html, done) {
var amperize = this;
var self = this;
async.reduce(data, html, function reduce(html, element, step) {
var children;
async.reduce(data, html, function reduce(html, element, step) {
var children;
function close(error, html) {
html += helpers.close(element);
step(null, html);
}
function close(error, html) {
html += helpers.close(element);
step(null, html);
}
function enter(error) {
children = element.children;
html += helpers[element.type](element);
function enter() {
children = element.children;
html += helpers[element.type](element);
if (!children || !children.length) return close(null, html);
if (!children || !children.length) {
return close(null, html);
}
setImmediate(function delay() {
traverse.call(amperize, children, html, close);
});
}
setImmediate(function delay() {
traverse.call(self, children, html, close);
});
}
function useSecureSchema(element) {
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;
}
function useSecureSchema(element) {
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;
}
function getLayoutAttribute(element) {
var layout;
function getLayoutAttribute(element) {
var layout;
// check if element.width is smaller than 300 px. In that case, we shouldn't use
// layout="responsive", because the media element will be stretched and it doesn't
// look nice. Use layout="fixed" instead to fix that.
layout = element.attribs.width < 300 ? layout = 'fixed' : self.config[element.name].layout;
// check if element.width is smaller than 300 px. In that case, we shouldn't use
// layout="responsive", because the media element will be stretched and it doesn't
// look nice. Use layout="fixed" instead to fix that.
layout = element.attribs.width < 300 ? layout = 'fixed' : amperize.config[element.name].layout;
element.attribs.layout = !element.attribs.layout ? layout : element.attribs.layout;
element.attribs.layout = !element.attribs.layout ? layout : element.attribs.layout;
return enter();
}
return enter();
}
/**
* 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 imageObj = url.parse(element.attribs.src),
requestOptions,
timeout = 3000;
/**
* 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 imageObj = url.parse(element.attribs.src),
requestOptions,
timeout = 3000;
if (!validator.isURL(imageObj.href)) {
// revert this element, do not show
element.name = 'img';
if (!validator.isURL(imageObj.href)) {
// revert this element, do not show
element.name = 'img';
return enter();
}
return enter();
}
// We need the user-agent, otherwise some https request may fail (e. g. cloudfare)
requestOptions = {
headers: {
'User-Agent': 'Mozilla/5.0'
},
timeout: timeout,
encoding: null
};
// We need the user-agent, otherwise some https request may fail (e. g. cloudfare)
requestOptions = {
headers: {
'User-Agent': 'Mozilla/5.0'
},
timeout: timeout,
encoding: null
};
return got(
imageObj.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);
return got (
imageObj.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;
}
// 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;
}
element.attribs.width = dimensions.width;
element.attribs.height = dimensions.height;
element.attribs.width = dimensions.width;
element.attribs.height = dimensions.height;
return getLayoutAttribute(element);
} catch (err) {
// revert this element, do not show
element.name = 'img';
return enter();
}
}).catch(function () {
// revert this element, do not show
element.name = 'img';
return enter();
});
}
return getLayoutAttribute(element);
} catch (err) {
// revert this element, do not show
element.name = 'img';
return enter();
if ((element.name === 'img' || element.name === 'iframe') && !element.attribs.src) {
return enter();
}
}).catch(function (err) {
// revert this element, do not show
element.name = 'img';
return enter();
});
}
if ((element.name === 'img' || element.name === 'iframe') && !element.attribs.src) {
return enter();
}
if (element.name === 'img' && self.config['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.name === 'img' && amperize.config['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.width || !element.attribs.height || !element.attribs.layout) {
if (element.attribs.src.indexOf('http') === 0) {
return getImageSize(element);
if (!element.attribs.width || !element.attribs.height || !element.attribs.layout) {
if (element.attribs.src.indexOf('http') === 0) {
return getImageSize(element);
}
}
// Fallback to default values for a local image
element.attribs.width = self.config['amp-img'].width;
element.attribs.height = self.config['amp-img'].height;
return getLayoutAttribute(element);
}
}
// Fallback to default values for a local image
element.attribs.width = amperize.config['amp-img'].width;
element.attribs.height = amperize.config['amp-img'].height;
return getLayoutAttribute(element);
}
if (element.name ==='iframe') {
element.name = 'amp-iframe';
if (element.name === 'iframe') {
element.name = 'amp-iframe';
if (!element.attribs.width || !element.attribs.height || !element.attribs.layout) {
if (!element.attribs.width || !element.attribs.height || !element.attribs.layout) {
element.attribs.width = !element.attribs.width ? self.config['amp-iframe'].width : element.attribs.width;
element.attribs.height = !element.attribs.height ? self.config['amp-iframe'].height : element.attribs.height;
element.attribs.sandbox = !element.attribs.sandbox ? self.config['amp-iframe'].sandbox : element.attribs.sandbox;
element.attribs.width = !element.attribs.width ? amperize.config['amp-iframe'].width : element.attribs.width;
element.attribs.height = !element.attribs.height ? amperize.config['amp-iframe'].height : element.attribs.height;
element.attribs.sandbox = !element.attribs.sandbox ? amperize.config['amp-iframe'].sandbox : element.attribs.sandbox;
useSecureSchema(element);
useSecureSchema(element);
return getLayoutAttribute(element);
}
}
return getLayoutAttribute(element);
}
}
if (element.name === 'audio') {
element.name = 'amp-audio';
}
if (element.name === 'audio') {
element.name = 'amp-audio';
}
useSecureSchema(element);
useSecureSchema(element);
return enter();
}, done);
return enter();
}, done);
};
module.exports = Amperize;
'use strict';
var node = [
'tag', 'script', 'style'
];
var node = ['tag', 'script', 'style'],
singular = [
'area', 'base', 'br', 'col', 'command', 'embed', 'hr',
'img', 'input', 'link', 'meta', 'param', 'source', 'wbr',
'track'
];
var singular = [
'area', 'base', 'br', 'col', 'command', 'embed', 'hr',
'img', 'input', 'link', 'meta', 'param', 'source', 'wbr',
'track'
];
function attributes(element) {
var attr = element.attribs
, name = element.name;
var attr = element.attribs;
if (!attr || typeof attr !== 'object') return '';
if (!attr || typeof attr !== 'object') {
return '';
}
return Object.keys(attr).reduce(function (result, key) {
return result + ' ' + key + '="' + attr[key] + '"';
}, '');
return Object.keys(attr).reduce(function (result, key) {
return result + ' ' + key + '="' + attr[key] + '"';
}, '');
}
exports.tag = exports.script = exports.style = function tag(element) {
return '<' + element.name + attributes(element) + '>';
return '<' + element.name + attributes(element) + '>';
};
exports.text = function text(element) {
return element.data;
return element.data;
};
exports.comment = function comment(element) {
return '<!--' + element.data + '-->';
return '<!--' + element.data + '-->';
};
exports.directive = function directive(element) {
return '<' + element.data + '>';
}
return '<' + element.data + '>';
};
exports.close = function close(element) {
return ~node.indexOf(element.type) && !~singular.indexOf(element.name)
? '</' + element.name + '>'
: '';
return ~node.indexOf(element.type) && !~singular.indexOf(element.name)
? '</' + element.name + '>'
: '';
};
{
"name": "amperize",
"version": "0.3.5",
"version": "0.3.6",
"description": "AMP up your plain HTML",

@@ -11,4 +11,7 @@ "main": "./lib/amperize",

"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"
"semantic-release": "semantic-release"
},
"engines": {
"node": "^4.5.0 || ^6.9.0 || ^8.9.0"
},
"repository": {

@@ -33,17 +36,17 @@ "type": "git",

"htmlparser2": "^3.9.2",
"image-size": "0.5.1",
"image-size": "0.6.1",
"lodash": "^4.17.4",
"nock": "^9.0.2",
"rewire": "^2.5.2",
"uuid": "^3.0.0",
"validator": "^8.2.0"
"validator": "^9.1.1"
},
"devDependencies": {
"chai": "^3.5.0",
"cz-conventional-changelog": "1.2.0",
"chai": "^4.1.2",
"cz-conventional-changelog": "2.1.0",
"istanbul": "^0.4.5",
"mocha": "^3.2.0",
"semantic-release": "6.3.2",
"sinon": "^1.17.7",
"sinon-chai": "^2.8.0"
"mocha": "^4.0.1",
"semantic-release": "9.1.0",
"sinon": "1.17.7",
"sinon-chai": "^2.8.0",
"nock": "^9.0.2",
"rewire": "^2.5.2"
},

@@ -50,0 +53,0 @@ "config": {

# Amperize
[![Version npm][version]](http://browsenpm.org/package/amperize)
[![Build Status][build]](https://travis-ci.org/jbhannah/amperize)
[![Dependencies][david]](https://david-dm.org/jbhannah/amperize)
[![Coverage Status][cover]](https://coveralls.io/r/jbhannah/amperize?branch=master)
[![Version npm](http://img.shields.io/npm/v/amperize.svg?style=flat)](http://browsenpm.org/package/amperize)
[![Build Status](http://img.shields.io/travis/jbhannah/amperize/master.svg?style=flat)](https://travis-ci.org/jbhannah/amperize)
[![Dependencies](https://img.shields.io/david/jbhannah/amperize.svg?style=flat)](https://david-dm.org/jbhannah/amperize)
[![Coverage Status](http://img.shields.io/coveralls/jbhannah/amperize/master.svg?style=flat)](https://coveralls.io/r/jbhannah/amperize?branch=master)
[version]: http://img.shields.io/npm/v/amperize.svg?style=flat
[build]: http://img.shields.io/travis/jbhannah/amperize/master.svg?style=flat
[david]: https://img.shields.io/david/jbhannah/amperize.svg?style=flat
[cover]: http://img.shields.io/coveralls/jbhannah/amperize/master.svg?style=flat
[AMP](https://github.com/ampproject/amphtml) up your plain HTML. Replaces regular HTML tags with their equivalent
[AMP components](https://github.com/ampproject/amphtml/blob/master/spec/amp-html-components.md).
[AMP][] up your plain HTML. Replaces regular HTML tags with their equivalent
[AMP components][].
## Installation
[AMP]: https://github.com/ampproject/amphtml
[AMP components]: https://github.com/ampproject/amphtml/blob/master/spec/amp-html-components.md
`npm install amperize`
## Node.js
```
var Amperize = require('amperize');
var html = '<img src="https://example.com/image.jpg" />';
amperize = new Amperize();
amperize.parse(html, function (error, result) {
if (error) {
// do something with error
return new Error(err);
}
}
// do something with result
return result;
});
```
## Restrictions
Amperize is build to convert the `<body>` part of your HTML. It will **not** create the AMP boilerplate and will **not** add the required `<script>` for each component.
## Currently supported AMP HTML components
### `<amp-img>`
**[`<amp-img>` reference](https://ampbyexample.com/components/amp-img/)**
Amperize will convert common `<img>` tags into AMP HTML conform `<amp-img>` tags. With the sub-dependency [`image-size`](https://github.com/image-size/image-size), Amperize will fetch the necessary `width` and `height` properties for the given image.
It will fall back to the default values `width: 600` and `height: 400`, if the dimensions couldn't get fetched.
If any other error occurs (eg. missing `src` property), Amperize will not transform the tag and return the original.
### `<amp-anim>`
**[`<amp-anim>` reference](https://ampbyexample.com/components/amp-anim/)**
When the `<img>` tag that needs to be transformed, is a `.gif` animation, Amperize will convert it into `<amp-anim>`, following the same rules as for `<amp-img>`.
### `<amp-iframe>`
**[`<amp-iframe>` reference](https://ampbyexample.com/components/amp-iframe/)**
Amperize converts iFrames like embedded videos from YouTube, Vimeo, etc. into `<amp-iframe>` tags.
### `<amp-audio>`
**[`<amp-audio>` reference](https://ampbyexample.com/components/amp-audio/)**
Converts HTML `<audio>` into `<amp-audio>`.
## Development
```
git clone git@github.com:jbhannah/amperize.git
cd amperize
npm install
npm run watch
```
`npm run watch` will restart the tests on changes.
### Tests
Running the test:
`npm run test`
Code coverage:
`npm run coverage`
## Credits
Borrows heavily from [Minimize][], especially the constructor, `parse`,
Borrows heavily from [Minimize](https://github.com/Swaagie/minimize), especially the constructor, `parse`,
`amperizer`, and `traverse` functions in the `Amperize` object, and the unit
tests. Copyright (c) 2013 Moveo - Martijn Swaagman. Used under the MIT License
(see `LICENSE`).
[Minimize]: https://github.com/Swaagie/minimize

@@ -1,12 +0,10 @@

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

@@ -16,472 +14,471 @@ chai.config.includeStack = true;

describe('Amperize', function () {
beforeEach(function () {
amperize = new Amperize();
});
afterEach(function () {
amperize = void 0;
});
describe('is a module', function () {
it('which has a constructor', function () {
expect(Amperize).to.be.a('function');
beforeEach(function () {
amperize = new Amperize();
});
it('which has default options', function () {
expect(amperize).to.have.property('config');
expect(amperize.config).to.be.eql({
'amp-img': {
layout: 'responsive',
width: 600,
height: 400,
},
'amp-anim': {
layout: 'responsive',
width: 600,
height: 400,
},
'amp-iframe': {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}
});
afterEach(function () {
amperize = undefined;
});
it('which can be configured', function () {
var configurable = new Amperize({some: 'options'});
expect(configurable).to.have.property('config');
expect(configurable.config.some).to.be.equal('options');
});
describe('is a module', function () {
it('which has a constructor', function () {
expect(Amperize).to.be.a('function');
});
it('which has htmlParser', function () {
expect(amperize).to.have.property('htmlParser');
expect(amperize.htmlParser).to.be.a('object');
});
it('which has default options', function () {
expect(amperize).to.have.property('config');
expect(amperize.config).to.be.eql({
'amp-img': {
layout: 'responsive',
width: 600,
height: 400
},
'amp-anim': {
layout: 'responsive',
width: 600,
height: 400
},
'amp-iframe': {
layout: 'responsive',
width: 600,
height: 400,
sandbox: 'allow-scripts allow-same-origin'
}
});
});
it('which has #parse', function () {
expect(amperize).to.have.property('parse');
expect(amperize.parse).to.be.a('function');
});
it('which can be configured', function () {
var configurable = new Amperize({some: 'options'});
expect(configurable).to.have.property('config');
expect(configurable.config.some).to.be.equal('options');
});
it('which has #amperizer', function () {
expect(amperize).to.have.property('amperizer');
expect(amperize.amperizer).to.be.a('function');
});
});
it('which has htmlParser', function () {
expect(amperize).to.have.property('htmlParser');
expect(amperize.htmlParser).to.be.a('object');
});
describe('#parse', function () {
var sizeOfMock,
sizeOfStub;
it('which has #parse', function () {
expect(amperize).to.have.property('parse');
expect(amperize.parse).to.be.a('function');
});
beforeEach(function () {
// stubbing the `image-size` lib, so we don't to a request everytime
sizeOfStub = sinon.stub();
it('which has #amperizer', function () {
expect(amperize).to.have.property('amperizer');
expect(amperize.amperizer).to.be.a('function');
});
});
afterEach(function () {
sinon.restore();
});
describe('#parse', function () {
var sizeOfMock,
sizeOfStub;
it('throws an error if no callback provided', function () {
function err() {
amperize.parse('', null);
}
beforeEach(function () {
// stubbing the `image-size` lib, so we don't to a request everytime
sizeOfStub = sinon.stub();
});
expect(err).throws('No callback provided');
});
afterEach(function () {
sinon.restore();
});
it('transforms small <img> into <amp-img></amp-img> with full image dimensions and fixed layout', function (done) {
sizeOfMock = nock('http://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
.reply(200, {
body: '<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>'
});
it('throws an error if no callback provided', function () {
function err() {
amperize.parse('', null);
}
sizeOfStub.returns({width: 50, height: 50, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
expect(err).throws('No callback provided');
});
amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256">', 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 small <img> into <amp-img></amp-img> with full image dimensions and fixed layout', function (done) {
sizeOfMock = nock('http://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
.reply(200, {
body: '<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>'
});
it('transforms big <img> into <amp-img></amp-img> with full image dimensions and responsive layout', function (done) {
sizeOfMock = nock('http://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
.reply(200, {
body: '<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">', 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();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms big <img> into <amp-img></amp-img> with full image dimensions and responsive layout', function (done) {
sizeOfMock = nock('http://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
.reply(200, {
body: '<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>'
});
amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256">', 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="responsive"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms <img> into <amp-img></amp-img> when width and height is set and overwrites it', function (done) {
sizeOfMock = nock('http://somestockwebsite.com')
.get('/image.jpg')
.reply(200, {
body: '<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>'
amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256">', 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="responsive"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms <img> into <amp-img></amp-img> when width and height is set and overwrites it', function (done) {
sizeOfMock = nock('http://somestockwebsite.com')
.get('/image.jpg')
.reply(200, {
body: '<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>'
});
amperize.parse('<img src="http://somestockwebsite.com/image.jpg" width="100" height="50">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms <img> into <amp-img></amp-img> does not overwrite layout attribute', function (done) {
sizeOfMock = nock('http://somestockwebsite.com')
.get('/image.jpg')
.reply(200, {
body: '<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>'
amperize.parse('<img src="http://somestockwebsite.com/image.jpg" width="100" height="50">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
expect(result).to.contain('layout="responsive"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms <img> into <amp-img></amp-img> does not overwrite layout attribute', function (done) {
sizeOfMock = nock('http://somestockwebsite.com')
.get('/image.jpg')
.reply(200, {
body: '<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>'
});
amperize.parse('<img src="http://somestockwebsite.com/image.jpg" layout="fixed">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
expect(result).to.contain('layout="fixed"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
sizeOfStub.returns({width: 350, height: 200, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('returns largest image value for .ico files', function (done) {
sizeOfMock = nock('https://somewebsite.com')
.get('/favicon.ico')
.reply(200, {
body: '<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: 32,
height: 32,
type: 'ico',
images: [
{width: 48, height: 48},
{width: 32, height: 32},
{width: 16, height: 16}
]
});
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="https://somewebsite.com/favicon.ico">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="https://somewebsite.com/favicon.ico"');
expect(result).to.contain('layout="fixed"');
expect(result).to.contain('width="48"');
expect(result).to.contain('height="48"');
expect(result).to.contain('</amp-img>');
done();
amperize.parse('<img src="http://somestockwebsite.com/image.jpg" layout="fixed">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
expect(result).to.contain('layout="fixed"');
expect(result).to.contain('width="350"');
expect(result).to.contain('height="200"');
expect(result).to.contain('</amp-img>');
done();
});
});
});
it('returns largest image value for .ico files', function (done) {
sizeOfMock = nock('https://somewebsite.com')
.get('/favicon.ico')
.reply(200, {
body: '<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>'
});
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, {
body: '<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: 32,
height: 32,
type: 'ico',
images: [
{width: 48, height: 48},
{width: 32, height: 32},
{width: 16, height: 16}
]
});
Amperize.__set__('sizeOf', sizeOfStub);
sizeOfStub.returns({width: 800, height: 600, type: 'gif'});
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="https://somewebsite.com/favicon.ico">', function (error, result) {
expect(result).to.exist;
expect(result).to.contain('<amp-img');
expect(result).to.contain('src="https://somewebsite.com/favicon.ico"');
expect(result).to.contain('layout="fixed"');
expect(result).to.contain('width="48"');
expect(result).to.contain('height="48"');
expect(result).to.contain('</amp-img>');
done();
});
});
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 .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, {
body: '<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>'
});
it('transforms <iframe> with only width property into <amp-iframe></amp-iframe> with full dimensions without 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();
});
});
sizeOfStub.returns({width: 800, height: 600, type: 'gif'});
Amperize.__set__('sizeOf', sizeOfStub);
it('transforms <iframe> with only height property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" height="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="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts allow-same-origin"')
done();
});
});
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 sandbox property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" sandbox="allow-scripts"></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="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts"')
done();
});
});
it('transforms <iframe> with only width property into <amp-iframe></amp-iframe> with full dimensions without 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('transforms <iframe> with only height property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" height="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="600"');
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 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 <iframe> with sandbox property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" sandbox="allow-scripts"></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="600"');
expect(result).to.contain('height="400"');
expect(result).to.contain('</amp-iframe>');
expect(result).to.contain('sandbox="allow-scripts"');
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('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('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('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('can handle invalid URLs', function (done) {
amperize.parse('<img src="http:not-a-website">', function (error, result) {
expect(result).to.exist;
expect(result).to.be.equal('<img src="http:not-a-website">');
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 <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('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('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('can handle invalid URLs', function (done) {
amperize.parse('<img src="http:not-a-website">', function (error, result) {
expect(result).to.exist;
expect(result).to.be.equal('<img src="http:not-a-website">');
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('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 <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('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('can handle redirects', function (done) {
var secondSizeOfMock;
sizeOfMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(301, {
body: '<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>'
},
{
location: 'http://someredirectedurl.com/files/f/feedough/x/11/1540353_20925115.jpg'
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();
});
});
secondSizeOfMock = nock('http://someredirectedurl.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(200, {
body: '<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>'
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();
});
});
sizeOfStub.returns({width: 100, height: 100, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
it('can handle redirects', function (done) {
var secondSizeOfMock;
sizeOfMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(301, {
body: '<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>'
},
{
location: 'http://someredirectedurl.com/files/f/feedough/x/11/1540353_20925115.jpg'
});
amperize.parse('<img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg">', function (error, result) {
expect(sizeOfMock.isDone()).to.be.equal(true);
expect(secondSizeOfMock.isDone()).to.be.equal(true);
expect(error).to.be.null;
expect(result).to.contain('<amp-img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg" width="100" height="100" layout="fixed"></amp-img>');
done();
});
});
secondSizeOfMock = nock('http://someredirectedurl.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(200, {
body: '<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>'
});
it('can handle request errors', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.reply(404, {message: 'something awful happened', code: 'AWFUL_ERROR'});
sizeOfStub.returns({width: 100, height: 100, type: 'jpg'});
Amperize.__set__('sizeOf', sizeOfStub);
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
});
amperize.parse('<img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg">', function (error, result) {
expect(sizeOfMock.isDone()).to.be.equal(true);
expect(secondSizeOfMock.isDone()).to.be.equal(true);
expect(error).to.be.null;
expect(result).to.contain('<amp-img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg" width="100" height="100" layout="fixed"></amp-img>');
done();
});
});
it('can handle errors of image-size module', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.reply(200, {
body: '<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>'
it('can handle request errors', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.reply(404, {message: 'something awful happened', code: 'AWFUL_ERROR'});
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
sizeOfStub.throws({error: 'image-size could not find dimensions'});
Amperize.__set__('sizeOf', sizeOfStub);
});
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
});
it('can handle errors of image-size module', function (done) {
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.reply(200, {
body: '<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({error: 'image-size could not find dimensions'});
Amperize.__set__('sizeOf', sizeOfStub);
it('can handle timeout errors', function (done) {
this.timeout(3500);
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
});
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.delay(3500)
.reply(200, {
body: '<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>'
it('can handle timeout errors', function (done) {
this.timeout(3500);
sizeOfMock = nock('http://example.com')
.get('/images/IMG_xyz.jpg')
.delay(3500)
.reply(200, {
body: '<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>'
});
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
expect(error).to.be.null;
expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg');
done();
});
});
});
});
describe('#amperizer', function () {
it('throws an error if HTML parsing failed', function () {
function err() {
amperize.amperizer('some error', []);
}
describe('#amperizer', function () {
it('throws an error if HTML parsing failed', function () {
function err() {
amperize.amperizer('some error', []);
}
expect(err).throws('Amperizer failed to parse DOM');
});
expect(err).throws('Amperizer failed to parse DOM');
});
it('should start traversing the DOM as soon as HTML parser is ready', function (done) {
var emit = sinon.spy(amperize, 'emit');
it('should start traversing the DOM as soon as HTML parser is ready', function (done) {
var emit = sinon.spy(amperize, 'emit');
amperize.parse('<html><body></body></html>', function () {
var first, second;
amperize.parse('<html><body></body></html>', function () {
expect(emit).to.be.calledTwice;
expect(emit).to.be.calledTwice;
var first = emit.getCall(0).args;
expect(first).to.be.an('array');
expect(first[0]).to.be.equal('read');
expect(first[1]).to.be.equal(null);
expect(first[2]).to.be.an('array');
first = emit.getCall(0).args;
expect(first).to.be.an('array');
expect(first[0]).to.be.equal('read');
expect(first[1]).to.be.equal(null);
expect(first[2]).to.be.an('array');
var second = emit.getCall(1).args;
expect(second).to.be.an('array');
expect(second[0]).to.be.include('parsed');
expect(second[1]).to.be.equal(null);
expect(second[2]).to.be.equal('<html><body></body></html>');
second = emit.getCall(1).args;
expect(second).to.be.an('array');
expect(second[0]).to.be.include('parsed');
expect(second[1]).to.be.equal(null);
expect(second[2]).to.be.equal('<html><body></body></html>');
done();
});
done();
});
});
});
});
});
'use strict';
var chai = require('chai')
, expect = chai.expect
, helpers = require('../lib/helpers');
var chai = require('chai'),
expect = chai.expect,
helpers = require('../lib/helpers');
describe('helpers', function () {
describe('#tag', function () {
it('returns an opening tag with attributes', function () {
var el = {
type: 'tag',
name: 'foo',
attribs: {
bar: 'bat'
}
};
describe('#tag', function () {
it('returns an opening tag with attributes', function () {
var el = {
type: 'tag',
name: 'foo',
attribs: {
bar: 'bat'
}
};
expect(helpers.tag(el)).to.be.equal('<foo bar="bat">');
});
expect(helpers.tag(el)).to.be.equal('<foo bar="bat">');
});
it('returns an opening tag without attributes', function () {
var el = {
type: 'tag',
name: 'foo'
};
it('returns an opening tag without attributes', function () {
var el = {
type: 'tag',
name: 'foo'
};
expect(helpers.tag(el)).to.be.equal('<foo>');
expect(helpers.tag(el)).to.be.equal('<foo>');
});
});
});
describe('#text', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'text',
data: 'some text'
};
describe('#text', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'text',
data: 'some text'
};
expect(helpers.text(el)).to.be.equal('some text');
expect(helpers.text(el)).to.be.equal('some text');
});
});
});
describe('#comment', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'comment',
data: 'some text'
};
describe('#comment', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'comment',
data: 'some text'
};
expect(helpers.comment(el)).to.be.equal('<!--some text-->');
expect(helpers.comment(el)).to.be.equal('<!--some text-->');
});
});
});
describe('#directive', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'directive',
data: '!DOCTYPE html'
};
describe('#directive', function () {
it('returns the element\'s contents', function () {
var el = {
type: 'directive',
data: '!DOCTYPE html'
};
expect(helpers.directive(el)).to.be.equal('<!DOCTYPE html>');
expect(helpers.directive(el)).to.be.equal('<!DOCTYPE html>');
});
});
});
describe('#close', function () {
it('closes non-singular tags', function () {
var el = {
type: 'tag',
name: 'foo'
};
describe('#close', function () {
it('closes non-singular tags', function () {
var el = {
type: 'tag',
name: 'foo'
};
expect(helpers.close(el)).to.be.equal('</foo>');
});
expect(helpers.close(el)).to.be.equal('</foo>');
});
it('does not close singular tags', function () {
var el = {
type: 'tag',
name: 'img'
};
it('does not close singular tags', function () {
var el = {
type: 'tag',
name: 'img'
};
expect(helpers.close(el)).to.be.equal('');
});
expect(helpers.close(el)).to.be.equal('');
});
it('does not close non-tags', function () {
var el = {
type: 'foo',
name: 'bar'
};
it('does not close non-tags', function () {
var el = {
type: 'foo',
name: 'bar'
};
expect(helpers.close(el)).to.be.equal('');
expect(helpers.close(el)).to.be.equal('');
});
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc