Comparing version 0.3.0 to 0.4.0-alpha
{ | ||
"name": "icojs", | ||
"description": "parse ico file", | ||
"version": "0.3.0", | ||
"version": "0.4.0-alpha", | ||
"author": "egy186", | ||
@@ -10,25 +10,29 @@ "bugs": { | ||
"dependencies": { | ||
"canvas": "^1.2.3" | ||
"jimp": "^0.2.21" | ||
}, | ||
"devDependencies": { | ||
"browserify": "^10.2.4", | ||
"babel-preset-es2015": "^6.3.13", | ||
"babelify": "^7.2.0", | ||
"browserify": "^12.0.1", | ||
"chai": "^3.0.0", | ||
"del": "^1.2.0", | ||
"gulp": "^3.9.0", | ||
"gulp-coveralls": "^0.1.4", | ||
"gulp-eslint": "^0.14.0", | ||
"gulp-istanbul": "^0.10.0", | ||
"gulp-mocha": "^2.1.2", | ||
"gulp-mustache": "^1.0.2", | ||
"gulp-sourcemaps": "^1.5.2", | ||
"gulp-uglify": "^1.2.0", | ||
"jsdoc": "^3.3.2", | ||
"vinyl-buffer": "^1.0.0", | ||
"vinyl-source-stream": "^1.1.0" | ||
"chai-as-promised": "^5.1.0", | ||
"eslint": "^1.10.3", | ||
"eslint-config-eslint": "^1.0.1", | ||
"istanbul": "^0.4.1", | ||
"jsdoc-to-markdown": "^1.3.1", | ||
"minifyify": "^7.1.0", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^2.3.4", | ||
"rimraf": "^2.4.4" | ||
}, | ||
"engines": { | ||
"node": ">=4.2.3" | ||
}, | ||
"files": [ | ||
"src", | ||
"LICENSE", | ||
"package.json", | ||
"README.md" | ||
"README.md", | ||
"browser.js", | ||
"index.js", | ||
"package.json" | ||
], | ||
@@ -41,3 +45,3 @@ "homepage": "https://egy186.github.io/icojs", | ||
"license": "MIT", | ||
"main": "src/ico.js", | ||
"main": "index.js", | ||
"repository": { | ||
@@ -48,5 +52,8 @@ "type": "git", | ||
"scripts": { | ||
"build": "gulp build", | ||
"test": "gulp test" | ||
"build": "mkdirp dist && browserify src/browser/index.js --debug --plugin [ minifyify --map ico.js.map --output dist/ico.js.map ] --transform babelify --standalone ICO --outfile dist/ico.js", | ||
"clean": "rimraf coverage dist", | ||
"doc": "jsdoc2md -f src/ico.js -t templates/README.md > README.md", | ||
"lint": "eslint src test", | ||
"test": "istanbul cover --root src --report lcov --dir coverage node_modules/mocha/bin/_mocha -- test/*.js" | ||
} | ||
} |
@@ -20,3 +20,5 @@ # icojs | ||
var arrayBuffer = new Uint8Array(fs.readFileSync('favicon.ico')).buffer; | ||
var images = ICO.parse(arrayBuffer); | ||
ICO.parse(arrayBuffer).then(images => { | ||
// do something | ||
}); | ||
``` | ||
@@ -28,4 +30,2 @@ | ||
__Prerequisite__: icojs relies on node-canvas, and you _must_ have installed __cairo__. Please see [node-canvas wiki](https://github.com/Automattic/node-canvas/wiki/_pages) for installation instructions. | ||
```sh | ||
@@ -47,5 +47,5 @@ npm install icojs | ||
To fully use this library, browsers must support **JavaScript typed arrays** and **Canvas API**. | ||
To fully use this library, browsers must support **JavaScript typed arrays**, **Canvas API** and **Promise**. | ||
Google Chrome, Internet Explorer 11, Mozilla Firefox and Safari 7.1 support these functions. | ||
Chrome, Edge 12, Firefox and Safari 9 support these functions. | ||
@@ -56,43 +56,45 @@ ## Demo | ||
<a name="ICO"></a> | ||
## Documentation | ||
### ICO.parse | ||
* [ICO](#ICO) | ||
* [.parse(buffer)](#ICO.parse) ⇒ <code>Promise.<Array.<Object>></code> | ||
* [.isICO(buffer)](#ICO.isICO) ⇒ <code>Boolean</code> | ||
* [.noConflict()](#ICO.noConflict) ⇒ <code>[ICO](#ICO)</code> | ||
<a name="ICO.parse"></a> | ||
### ICO.parse(buffer) ⇒ <code>Promise.<Array.<Object>></code> | ||
Parse ICO and return some PNGs. | ||
#### Parameters | ||
* `buffer` **ArrayBuffer** - The ArrayBuffer object contain the TypedArray of a ICO file. | ||
#### Returns | ||
* **Array.<Object>** - Array of parsed ICO. | ||
**Kind**: static method of <code>[ICO](#ICO)</code> | ||
**Returns**: <code>Promise.<Array.<Object>></code> - Resolves to array of parsed ICO. | ||
* `width` **Number** - Image width. | ||
* `height` **Number** - Image height. | ||
* `bit` **Number** - Image bit depth. | ||
* `buffer` **ArrayBuffer** - Image buffer. | ||
* `buffer` **ArrayBuffer** - Image buffer. | ||
### ICO.isICO | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| buffer | <code>ArrayBuffer</code> | The ArrayBuffer object contain the TypedArray of a ICO file. | | ||
<a name="ICO.isICO"></a> | ||
### ICO.isICO(buffer) ⇒ <code>Boolean</code> | ||
Check the ArrayBuffer is valid ICO. | ||
#### Parameters | ||
**Kind**: static method of <code>[ICO](#ICO)</code> | ||
**Returns**: <code>Boolean</code> - True if arg is ICO. | ||
* `buffer` **ArrayBuffer** - The ArrayBuffer object contain the TypedArray of a ICO file. | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| buffer | <code>ArrayBuffer</code> | The ArrayBuffer object contain the TypedArray of a ICO file. | | ||
#### Returns | ||
* **Boolean** - True if arg is ICO. | ||
### ICO.noConflict | ||
<a name="ICO.noConflict"></a> | ||
### ICO.noConflict() ⇒ <code>[ICO](#ICO)</code> | ||
No conflict. | ||
**Kind**: static method of <code>[ICO](#ICO)</code> | ||
**Returns**: <code>[ICO](#ICO)</code> - `ICO` Object. | ||
#### Returns | ||
* **ICO** - `ICO` Object. | ||
## License | ||
MIT license |
293
src/ico.js
@@ -1,220 +0,95 @@ | ||
/* global global: false */ | ||
'use strict'; | ||
var extractOne = require('./extractone'); | ||
var PNG = require('./png'); | ||
var util = require('./util'); | ||
const extractOne = require('./extract-one'); | ||
const imageData = require('./image-data'); | ||
/** | ||
* make 1bit image imageData.data | ||
* @private | ||
* @param {Object} ico should have width, height, bit, colors, xor, and | ||
* @returns {Uint8ClampedArray} imageData.data | ||
*/ | ||
var make1bitImageData = function (ico) { | ||
var color; | ||
var xor = util.to1bitArray(ico.xor); | ||
var and = util.to1bitArray(ico.and); | ||
var xorLine = util.toDividableBy4(ico.width * ico.bit / 8) * 8 / ico.bit; | ||
var andLine = util.toDividableBy4(ico.width / 8) * 8; | ||
var index = 0; | ||
var data = new Uint8ClampedArray(ico.width * ico.height * 4); | ||
for (var h = ico.height - 1; h >= 0; h--) { | ||
for (var w = 0; w < ico.width; w++) { | ||
color = ico.colors[xor[h * xorLine + w]]; | ||
data[index] = color[2]; | ||
data[index + 1] = color[1]; | ||
data[index + 2] = color[0]; | ||
data[index + 3] = and[h * andLine + w] ? 0 : 255; | ||
index += 4; | ||
} | ||
} | ||
return data; | ||
}; | ||
const range = n => new Array(n).fill(0).map((_, i) => i); | ||
/** | ||
* make 4bit image imageData.data | ||
* @private | ||
* @param {Object} ico should have width, height, bit, colors, xor, and | ||
* @returns {Uint8ClampedArray} imageData.data | ||
*/ | ||
var make4bitImageData = function (ico) { | ||
var color; | ||
var xor = util.to4bitArray(ico.xor); | ||
var and = util.to1bitArray(ico.and); | ||
var xorLine = util.toDividableBy4(ico.width * ico.bit / 8) * 8 / ico.bit; | ||
var andLine = util.toDividableBy4(ico.width / 8) * 8; | ||
var index = 0; | ||
var data = new Uint8ClampedArray(ico.width * ico.height * 4); | ||
for (var h = ico.height - 1; h >= 0; h--) { | ||
for (var w = 0; w < ico.width; w++) { | ||
color = ico.colors[xor[h * xorLine + w]]; | ||
data[index] = color[2]; | ||
data[index + 1] = color[1]; | ||
data[index + 2] = color[0]; | ||
data[index + 3] = and[h * andLine + w] ? 0 : 255; | ||
index += 4; | ||
} | ||
} | ||
return data; | ||
}; | ||
* @class ICO | ||
*/ | ||
/** | ||
* make 8bit image imageData.data | ||
* @private | ||
* @param {Object} ico should have width, height, bit, colors, xor, and | ||
* @returns {Uint8ClampedArray} imageData.data | ||
*/ | ||
var make8bitImageData = function (ico) { | ||
var color; | ||
var xor = new Uint8Array(ico.xor); | ||
var and = util.to1bitArray(ico.and); | ||
var xorLine = util.toDividableBy4(ico.width * ico.bit / 8) * 8 / ico.bit; | ||
var andLine = util.toDividableBy4(ico.width / 8) * 8; | ||
var index = 0; | ||
var data = new Uint8ClampedArray(ico.width * ico.height * 4); | ||
index = 0; | ||
for (var h = ico.height - 1; h >= 0; h--) { | ||
for (var w = 0; w < ico.width; w++) { | ||
color = ico.colors[xor[h * xorLine + w]]; | ||
data[index] = color[2]; | ||
data[index + 1] = color[1]; | ||
data[index + 2] = color[0]; | ||
data[index + 3] = and[h * andLine + w] ? 0 : 255; | ||
index += 4; | ||
} | ||
} | ||
return data; | ||
}; | ||
/** | ||
* make 24bit image imageData.data | ||
* @private | ||
* @param {Object} ico should have width, height, bit, xor, and | ||
* @returns {Uint8ClampedArray} imageData.data | ||
*/ | ||
var make24bitImageData = function (ico) { | ||
var xor = new Uint8Array(ico.xor); | ||
var and = util.to1bitArray(ico.and); | ||
var xorLine = util.toDividableBy4(ico.width * ico.bit / 8) * 8 / ico.bit; | ||
var andLine = util.toDividableBy4(ico.width / 8) * 8; | ||
var index = 0; | ||
var data = new Uint8ClampedArray(ico.width * ico.height * 4); | ||
for (var h = ico.height - 1; h >= 0; h--) { | ||
for (var w = 0; w < ico.width; w++) { | ||
data[index] = xor[(h * xorLine + w) * 3 + 2]; | ||
data[index + 1] = xor[(h * xorLine + w) * 3 + 1]; | ||
data[index + 2] = xor[(h * xorLine + w) * 3]; | ||
data[index + 3] = and[h * andLine + w] ? 0 : 255; | ||
index += 4; | ||
} | ||
} | ||
return data; | ||
}; | ||
/** | ||
* make 32bit image imageData.data | ||
* @private | ||
* @param {Object} ico should have width, height, bit, xor, and | ||
* @returns {Uint8ClampedArray} imageData.data | ||
*/ | ||
var make32bitImageData = function (ico) { | ||
var xor = new Uint8Array(ico.xor); | ||
var and = util.to1bitArray(ico.and); | ||
var xorLine = util.toDividableBy4(ico.width * ico.bit / 8) * 8 / ico.bit; | ||
var andLine = util.toDividableBy4(ico.width / 8) * 8; | ||
var index = 0; | ||
var data = new Uint8ClampedArray(ico.width * ico.height * 4); | ||
for (var h = ico.height - 1; h >= 0; h--) { | ||
for (var w = 0; w < ico.width; w++) { | ||
data[index] = xor[(h * xorLine + w) * 4 + 2]; | ||
data[index + 1] = xor[(h * xorLine + w) * 4 + 1]; | ||
data[index + 2] = xor[(h * xorLine + w) * 4]; | ||
data[index + 3] = and[h * andLine + w] === 1 || xor[(h * xorLine + w) * 4 + 3] === 1 ? 0 : xor[(h * xorLine + w) * 4 + 3] > 1 ? xor[(h * xorLine + w) * 4 + 3] : 255; | ||
index += 4; | ||
} | ||
} | ||
return data; | ||
}; | ||
var previousICO = global.ICO; | ||
/** | ||
* @class ICO | ||
*/ | ||
var ICO = { | ||
/** | ||
* Parse ICO and return some PNGs. | ||
* @param {ArrayBuffer} buffer The ArrayBuffer object contain the TypedArray of a ICO file. | ||
* @returns {Object[]} Array of parsed ICO. | ||
* * `width` **Number** - Image width. | ||
* * `height` **Number** - Image height. | ||
* * `bit` **Number** - Image bit depth. | ||
* * `buffer` **ArrayBuffer** - Image buffer. | ||
*/ | ||
parse: function (buffer) { | ||
var icoDv = new DataView(buffer); | ||
if (icoDv.getUint16(0, true) !== 0 || icoDv.getUint16(2, true) !== 1) { | ||
throw new Error('buffer is not ico'); | ||
} | ||
// make single image icon | ||
var ico, data; | ||
var icos = []; | ||
// var idCount = icoDv.getUint16(4, true); | ||
for (var i = 0; i < icoDv.getUint16(4, true); i++) { | ||
ico = extractOne(buffer, i); | ||
switch (ico.bit) { | ||
case 1: | ||
data = make1bitImageData(ico); | ||
break; | ||
case 4: | ||
data = make4bitImageData(ico); | ||
break; | ||
case 8: | ||
data = make8bitImageData(ico); | ||
break; | ||
case 24: | ||
data = make24bitImageData(ico); | ||
break; | ||
case 32: | ||
data = make32bitImageData(ico); | ||
break; | ||
const factory = config => { | ||
const previousICO = global.ICO; | ||
const ICO = { | ||
/** | ||
* Parse ICO and return some PNGs. | ||
* @memberof ICO | ||
* @param {ArrayBuffer} buffer The ArrayBuffer object contain the TypedArray of a ICO file. | ||
* @returns {Promise<Object[]>} Resolves to array of parsed ICO. | ||
* * `width` **Number** - Image width. | ||
* * `height` **Number** - Image height. | ||
* * `bit` **Number** - Image bit depth. | ||
* * `buffer` **ArrayBuffer** - Image buffer. | ||
*/ | ||
parse (buffer) { | ||
const icoDv = new DataView(buffer); | ||
if (icoDv.getUint16(0, true) !== 0 || icoDv.getUint16(2, true) !== 1) { | ||
return Promise.reject(new Error('buffer is not ico')); | ||
} | ||
icos.push({ | ||
bit: ico.bit, | ||
width: ico.width, | ||
height: ico.height, | ||
buffer: PNG.encode({ | ||
// make single image icon | ||
// let idCount = icoDv.getUint16(4, true); | ||
const icos = Promise.all(range(icoDv.getUint16(4, true)).map(i => { | ||
let data; | ||
const ico = extractOne(buffer, i); | ||
switch (ico.bit) { // eslint-disable-line default-case | ||
case 1: | ||
data = imageData.from1bit(ico); | ||
break; | ||
case 4: | ||
data = imageData.from4bit(ico); | ||
break; | ||
case 8: | ||
data = imageData.from8bit(ico); | ||
break; | ||
case 24: | ||
data = imageData.from24bit(ico); | ||
break; | ||
case 32: | ||
data = imageData.from32bit(ico); | ||
break; | ||
} | ||
return config.PNG.encode({ | ||
width: ico.width, | ||
height: ico.height, | ||
data: data | ||
}) | ||
}); | ||
data | ||
}).then(pngBuffer => { | ||
return { | ||
bit: ico.bit, | ||
width: ico.width, | ||
height: ico.height, | ||
buffer: pngBuffer | ||
}; | ||
}); | ||
})); | ||
return icos; | ||
}, | ||
/** | ||
* Check the ArrayBuffer is valid ICO. | ||
* @memberof ICO | ||
* @param {ArrayBuffer} buffer The ArrayBuffer object contain the TypedArray of a ICO file. | ||
* @returns {Boolean} True if arg is ICO. | ||
*/ | ||
isICO (buffer) { | ||
if (!(buffer instanceof ArrayBuffer)) { | ||
return false; | ||
} | ||
const icoDv = new DataView(buffer); | ||
// idReserved = icoDv.getUint16(0, true) | ||
// idType = icoDv.getUint16(0, true) | ||
return icoDv.getUint16(0, true) === 0 && icoDv.getUint16(2, true) === 1; | ||
}, | ||
/** | ||
* No conflict. | ||
* @memberof ICO | ||
* @returns {ICO} `ICO` Object. | ||
*/ | ||
noConflict () { | ||
global.ICO = previousICO; | ||
return this; | ||
} | ||
return icos; | ||
}, | ||
/** | ||
* Check the ArrayBuffer is valid ICO. | ||
* @param {ArrayBuffer} buffer The ArrayBuffer object contain the TypedArray of a ICO file. | ||
* @returns {Boolean} True if arg is ICO. | ||
*/ | ||
isICO: function (buffer) { | ||
if (!(buffer instanceof ArrayBuffer)) { | ||
return false; | ||
} | ||
var icoDv = new DataView(buffer); | ||
// idReserved = icoDv.getUint16(0, true) | ||
// idType = icoDv.getUint16(0, true) | ||
return icoDv.getUint16(0, true) === 0 && icoDv.getUint16(2, true) === 1; | ||
}, | ||
/** | ||
* No conflict. | ||
* @returns {ICO} `ICO` Object. | ||
*/ | ||
noConflict: function () { | ||
global.ICO = previousICO; | ||
return this; | ||
} | ||
}; | ||
return ICO; | ||
}; | ||
module.exports = ICO; | ||
global.ICO = ICO; | ||
module.exports = factory; |
@@ -1,35 +0,12 @@ | ||
/* global global: false */ | ||
'use strict'; | ||
/* istanbul ignore next */ | ||
var createCanvas = global.document ? function (width, height) { | ||
var canvas = global.document.createElement('canvas'); | ||
canvas.width = width; | ||
canvas.height = height; | ||
return canvas; | ||
} : function (width, height) { | ||
var Canvas = require('canvas'); | ||
return new Canvas(width, height); | ||
}; | ||
const Jimp = require('jimp'); | ||
/* istanbul ignore next */ | ||
/* jshint -W079 */ | ||
var atob = global.atob ? global.atob : function (str) { | ||
/* jshint +W079 */ | ||
var Buffer = require('buffer').Buffer; | ||
return new Buffer(str, 'base64').toString('binary'); | ||
}; | ||
const bufferToArrayBuffer = require('./utils/buffer-to-arraybuffer'); | ||
var dataURLToArrayBuffer = function (dataURL) { | ||
var string = atob(dataURL.replace(/.+,/, '')); | ||
var bytes = new Uint8Array(string.length); | ||
for (var i = 0; i < string.length; i++) { | ||
bytes[i] = string.charCodeAt(i); | ||
} | ||
return bytes.buffer; | ||
}; | ||
var PNG = { | ||
const PNG = { | ||
/** | ||
* create png from imgData.data | ||
* @param {Object} data | ||
* @access private | ||
* @param {Object} image data | ||
* @param {Number} image.width img width | ||
@@ -40,26 +17,24 @@ * @param {Number} image.height img height | ||
*/ | ||
encode: function (image) { | ||
var data = image.data; | ||
var canvas = createCanvas(image.width, image.height); | ||
var ctx = canvas.getContext('2d'); | ||
var imageData = ctx.createImageData(image.width, image.height); | ||
var dataData = imageData.data; | ||
for (var i = 0; i < dataData.length; i++) { | ||
dataData[i] = data[i]; | ||
} | ||
ctx.putImageData(imageData, 0, 0); | ||
return dataURLToArrayBuffer(canvas.toDataURL()); | ||
encode (image) { | ||
const data = image.data; | ||
const jimp = new Jimp(image.width, image.height); | ||
jimp.scan(0, 0, jimp.bitmap.width, jimp.bitmap.height, function (x, y, idx) { | ||
this.bitmap.data[idx + 0] = data[idx + 0]; // eslint-disable-line no-invalid-this | ||
this.bitmap.data[idx + 1] = data[idx + 1]; // eslint-disable-line no-invalid-this | ||
this.bitmap.data[idx + 2] = data[idx + 2]; // eslint-disable-line no-invalid-this | ||
this.bitmap.data[idx + 3] = data[idx + 3]; // eslint-disable-line no-invalid-this | ||
}); | ||
return new Promise((resolve, reject) => { | ||
jimp.getBuffer(Jimp.MIME_PNG, (err, buffer) => { | ||
/* istanbul ignore if */ | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(bufferToArrayBuffer(buffer)); | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* create imgData.data from png | ||
* @param {ArrayBuffer} buffer png | ||
* @returns {Object} data | ||
* @returns {Number} image.width | ||
* @returns {Number} image.height | ||
* @returns {Uint8ClampedArray} image.data | ||
*/ | ||
/*decode: function (buffer) { | ||
}*/ | ||
}; | ||
module.exports = PNG; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19000
13
15
424
97
1
+ Addedjimp@^0.2.21
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedbignumber.js@2.4.0(transitive)
+ Addedbmp-js@0.0.3(transitive)
+ Addedbuffer-equal@0.0.1(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcentra@2.7.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addeddom-walk@0.1.2(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedes6-promise@3.3.1(transitive)
+ Addedexif-parser@0.1.12(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfile-type@3.9.0(transitive)
+ Addedfollow-redirects@1.15.9(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedglobal@4.4.0(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedip-regex@1.0.3(transitive)
+ Addedis-function@1.0.2(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjimp@0.2.28(transitive)
+ Addedjpeg-js@0.2.0(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedload-bmfont@1.4.2(transitive)
+ Addedmime@1.6.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedmin-document@2.19.0(transitive)
+ Addedminimist@0.0.8(transitive)
+ Addedmkdirp@0.5.1(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedparse-bmfont-ascii@1.0.6(transitive)
+ Addedparse-bmfont-binary@1.0.6(transitive)
+ Addedparse-bmfont-xml@1.1.6(transitive)
+ Addedparse-headers@2.0.5(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedphin@3.7.1(transitive)
+ Addedpixelmatch@4.0.2(transitive)
+ Addedpngjs@3.4.0(transitive)
+ Addedprocess@0.11.10(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedread-chunk@1.0.1(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsax@1.4.1(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedstream-to@0.2.2(transitive)
+ Addedstream-to-buffer@0.1.0(transitive)
+ Addedtinycolor2@1.6.0(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedurl-regex@3.2.0(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)
+ Addedxhr@2.6.0(transitive)
+ Addedxml-parse-from-string@1.0.1(transitive)
+ Addedxml2js@0.5.0(transitive)
+ Addedxmlbuilder@11.0.1(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedcanvas@^1.2.3
- Removedcanvas@1.6.13(transitive)
- Removednan@2.22.0(transitive)