Comparing version 0.13.1 to 0.14.0
@@ -44,5 +44,5 @@ # Contributing to sharp | ||
| ------: | :--------- | | ||
| v0.14.0 | needle | | ||
| v0.15.0 | outfit | | ||
| v0.16.0 | pencil | | ||
| v0.17.0 | quill | | ||
@@ -49,0 +49,0 @@ Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`. |
104
docs/api.md
@@ -30,2 +30,3 @@ # API | ||
JPEG, PNG or WebP format image data can be streamed out from this object. | ||
When using Stream based output, derived attributes are available from the `info` event. | ||
@@ -41,2 +42,15 @@ ```javascript | ||
```javascript | ||
// Read image data from readableStream, | ||
// resize to 300 pixels wide, | ||
// emit an 'info' event with calculated dimensions | ||
// and finally write image data to writableStream | ||
var transformer = sharp() | ||
.resize(300) | ||
.on('info', function(info) { | ||
console.log('Image height is ' + info.height); | ||
}); | ||
readableStream.pipe(transformer).pipe(writableStream); | ||
``` | ||
#### metadata([callback]) | ||
@@ -53,2 +67,3 @@ | ||
* `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK | ||
* `density`: Number of pixels per inch (DPI), if present | ||
* `hasProfile`: Boolean indicating the presence of an embedded ICC profile | ||
@@ -116,19 +131,33 @@ * `hasAlpha`: Boolean indicating the presence of an alpha transparency channel | ||
#### crop([gravity]) | ||
#### crop([option]) | ||
Crop the resized image to the exact size specified, the default behaviour. | ||
`gravity`, if present, is a String or an attribute of the `sharp.gravity` Object e.g. `sharp.gravity.north`. | ||
`option`, if present, is an attribute of: | ||
Possible values are `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` and `centre`. | ||
The default gravity is `center`/`centre`. | ||
* `sharp.gravity` e.g. `sharp.gravity.north`, to crop to an edge or corner, or | ||
* `sharp.strategy` e.g. `sharp.strategy.entropy`, to crop dynamically. | ||
Possible attributes of `sharp.gravity` are | ||
`north`, `northeast`, `east`, `southeast`, `south`, | ||
`southwest`, `west`, `northwest`, `center` and `centre`. | ||
Possible attributes of the experimental `sharp.strategy` are: | ||
* `entropy`: resize so one dimension is at its target size | ||
then repeatedly remove pixels from the edge with the lowest | ||
[Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29) | ||
until it too reaches the target size. | ||
The default crop option is a `center`/`centre` gravity. | ||
```javascript | ||
var transformer = sharp() | ||
.resize(300, 200) | ||
.crop(sharp.gravity.north) | ||
.resize(200, 200) | ||
.crop(sharp.strategy.entropy) | ||
.on('error', function(err) { | ||
console.log(err); | ||
}); | ||
// Read image data from readableStream, resize and write image data to writableStream | ||
// Read image data from readableStream | ||
// Write 200px square auto-cropped image data to writableStream | ||
readableStream.pipe(transformer).pipe(writableStream); | ||
@@ -272,3 +301,3 @@ ``` | ||
Set the background for the `embed` and `flatten` operations. | ||
Set the background for the `embed`, `flatten` and `extend` operations. | ||
@@ -285,2 +314,21 @@ `rgba` is parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. | ||
#### extend(extension) | ||
Extends/pads the edges of the image with `background`, where `extension` is one of: | ||
* a Number representing the pixel count to add to each edge, or | ||
* an Object containing `top`, `left`, `bottom` and `right` attributes, each a Number of pixels to add to that edge. | ||
This operation will always occur after resizing and extraction, if any. | ||
```javascript | ||
// Resize to 140 pixels wide, then add 10 transparent pixels | ||
// to the top, left and right edges and 20 to the bottom edge | ||
sharp(input) | ||
.resize(140) | ||
.background({r: 0, g: 0, b: 0, a: 0}) | ||
.extend({top: 10, bottom: 20, left: 10, right: 10}) | ||
... | ||
``` | ||
#### negate() | ||
@@ -374,10 +422,15 @@ | ||
#### overlayWith(path) | ||
#### overlayWith(image, [options]) | ||
_Experimental_ | ||
Overlay (composite) a image containing an alpha channel over the processed (resized, extracted etc.) image. | ||
Alpha composite image at `path` over the processed (resized, extracted) image. The dimensions of the two images must match. | ||
`image` is one of the following, and must be the same size or smaller than the processed image: | ||
* `path` is a String containing the path to an image file with an alpha channel. | ||
* Buffer containing PNG, WebP, GIF or SVG image data, or | ||
* String containing the path to an image file, with most major transparency formats supported. | ||
`options`, if present, is an Object with the following optional attributes: | ||
* `gravity` is a String or an attribute of the `sharp.gravity` Object e.g. `sharp.gravity.north` at which to place the overlay, defaulting to `center`/`centre`. | ||
```javascript | ||
@@ -389,3 +442,3 @@ sharp('input.png') | ||
.background('#ff6600') | ||
.overlayWith('overlay.png') | ||
.overlayWith('overlay.png', { gravity: sharp.gravity.southeast } ) | ||
.sharpen() | ||
@@ -398,4 +451,4 @@ .withMetadata() | ||
// outputBuffer contains upside down, 300px wide, alpha channel flattened | ||
// onto orange background, composited with overlay.png, sharpened, | ||
// with metadata, 90% quality WebP image data. Phew! | ||
// onto orange background, composited with overlay.png with SE gravity, | ||
// sharpened, with metadata, 90% quality WebP image data. Phew! | ||
}); | ||
@@ -478,3 +531,3 @@ ``` | ||
* `orientation` is an integral Number between 0 and 7, used to update the value of the EXIF `Orientation` tag. | ||
* `orientation` is an integral Number between 1 and 8, used to update the value of the EXIF `Orientation` tag. | ||
This has no effect if the input image does not have an EXIF `Orientation` tag. | ||
@@ -484,14 +537,21 @@ | ||
#### tile([size], [overlap]) | ||
#### tile(options) | ||
The size and overlap, in pixels, of square Deep Zoom image pyramid tiles. | ||
The size, overlap and directory layout to use when generating square Deep Zoom image pyramid tiles. | ||
`options` is an Object with one or more of the following attributes: | ||
* `size` is an integral Number between 1 and 8192. The default value is 256 pixels. | ||
* `overlap` is an integral Number between 0 and 8192. The default value is 0 pixels. | ||
* `layout` is a String, with value `dz`, `zoomify` or `google`. The default value is `dz`. | ||
```javascript | ||
sharp('input.tiff').tile(256).toFile('output.dzi', function(err, info) { | ||
// The output.dzi file is the XML format Deep Zoom definition | ||
// The output_files directory contains 256x256 pixel tiles grouped by zoom level | ||
}); | ||
sharp('input.tiff') | ||
.tile({ | ||
size: 512 | ||
}) | ||
.toFile('output.dzi', function(err, info) { | ||
// output.dzi is the Deep Zoom XML definition | ||
// output_files contains 512x512 tiles grouped by zoom level | ||
}); | ||
``` | ||
@@ -498,0 +558,0 @@ |
# Changelog | ||
### v0.14 - "*needle*" | ||
Requires libvips v8.2.3 | ||
#### v0.14.0 - 2<sup>nd</sup> April 2016 | ||
* Add ability to extend (pad) the edges of an image. | ||
[#128](https://github.com/lovell/sharp/issues/128) | ||
[@blowsie](https://github.com/blowsie) | ||
* Add support for Zoomify and Google tile layouts. Breaks existing tile API. | ||
[#223](https://github.com/lovell/sharp/issues/223) | ||
[@bdunnette](https://github.com/bdunnette) | ||
* Improvements to overlayWith: differing sizes/formats, gravity, buffer input. | ||
[#239](https://github.com/lovell/sharp/issues/239) | ||
[@chrisriley](https://github.com/chrisriley) | ||
* Add entropy-based crop strategy to remove least interesting edges. | ||
[#295](https://github.com/lovell/sharp/issues/295) | ||
[@rightaway](https://github.com/rightaway) | ||
* Expose density metadata; set density of images from vector input. | ||
[#338](https://github.com/lovell/sharp/issues/338) | ||
[@lookfirst](https://github.com/lookfirst) | ||
* Emit post-processing 'info' event for Stream output. | ||
[#367](https://github.com/lovell/sharp/issues/367) | ||
[@salzhrani](https://github.com/salzhrani) | ||
* Ensure output image EXIF Orientation values are within 1-8 range. | ||
[#385](https://github.com/lovell/sharp/pull/385) | ||
[@jtobinisaniceguy](https://github.com/jtobinisaniceguy) | ||
* Ensure ratios are not swapped when rotating 90/270 and ignoring aspect. | ||
[#387](https://github.com/lovell/sharp/issues/387) | ||
[@kleisauke](https://github.com/kleisauke) | ||
### v0.13 - "*mind*" | ||
Requires libvips v8.2.2 | ||
#### v0.13.1 - 27<sup>th</sup> February 2016 | ||
@@ -58,2 +98,4 @@ | ||
Requires libvips v8.2.0 | ||
#### v0.12.2 - 16<sup>th</sup> January 2016 | ||
@@ -60,0 +102,0 @@ |
@@ -17,3 +17,3 @@ # Installation | ||
libvips and its dependencies are fetched and stored within `node_modules/sharp` during `npm install`. | ||
libvips and its dependencies are fetched and stored within `node_modules/sharp/lib` during `npm install`. | ||
This involves an automated HTTPS download of approximately 6MB. | ||
@@ -30,5 +30,12 @@ | ||
* Raspbian Jessie | ||
* Amazon Linux 2015.03, 2015.09 | ||
Preference will be given to an existing globally-installed (via `pkg-config`) | ||
version of libvips that meets the minimum version requirement. | ||
To use your own version of libvips instead of the provided binaries, make sure it is | ||
at least the version listed under `config.libvips` in the `package.json` file that it | ||
can be located using `pkg-config`. If you are using non-stadard paths (anything other | ||
than `/usr` or `/usr/local`), you might need to set `PKG_CONFIG_PATH` during `npm install` | ||
and `LD_LIBRARY_PATH` at runtime. | ||
You can print the detected vips version using: `pkg-config --modversion vips-cpp` | ||
This allows the use of newer versions of libvips with older versions of sharp. | ||
@@ -118,2 +125,30 @@ | ||
### AWS Lambda | ||
In order to use sharp on AWS Lambda, you need to [create a deployment package](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html). Because sharp | ||
downloads and links libraries for the current platform during `npm install` you have to | ||
do this on a system similar to the [Lambda Execution Environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html). The easiest ways to do this, is to setup a | ||
small t2.micro instance using the AMI ID listed in the previous link, ssh into it as ec2-user | ||
and follow the instructions below. | ||
Install depencies: | ||
```sh | ||
sudo yum-config-manager --enable epel | ||
sudo yum install -y nodejs gcc-c++ | ||
curl -s https://www.npmjs.com/install.sh | sudo sh | ||
``` | ||
Copy your code and package.json to the instance using `scp` and create a deployment package: | ||
```sh | ||
cd sharp-lambda-example | ||
npm install | ||
zip -ur9 ../sharp-lambda-example.zip index.js node_modules | ||
``` | ||
You can now download your deployment ZIP using `scp` and upload it to Lambda. | ||
**Performance Tip:** To get the best performance on Lambda choose the largest memory available because this also gives you the most cpu time (a 1536 MB function is 12x faster than a 128 MB function). | ||
### Build tools | ||
@@ -120,0 +155,0 @@ |
198
index.js
@@ -49,3 +49,3 @@ 'use strict'; | ||
limitInputPixels: maximum.pixels, | ||
density: '72', | ||
density: 72, | ||
rawWidth: 0, | ||
@@ -68,3 +68,3 @@ rawHeight: 0, | ||
canvas: 'crop', | ||
gravity: 0, | ||
crop: 0, | ||
angle: 0, | ||
@@ -74,2 +74,6 @@ rotateBeforePreExtract: false, | ||
flop: false, | ||
extendTop: 0, | ||
extendBottom: 0, | ||
extendLeft: 0, | ||
extendRight: 0, | ||
withoutEnlargement: false, | ||
@@ -90,3 +94,5 @@ interpolator: 'bicubic', | ||
// overlay | ||
overlayPath: '', | ||
overlayFileIn: '', | ||
overlayBufferIn: null, | ||
overlayGravity: 0, | ||
// output options | ||
@@ -113,9 +119,9 @@ formatOut: 'input', | ||
}; | ||
if (typeof input === 'string') { | ||
if (isString(input)) { | ||
// input=file | ||
this.options.fileIn = input; | ||
} else if (typeof input === 'object' && input instanceof Buffer) { | ||
} else if (isBuffer(input)) { | ||
// input=buffer | ||
this.options.bufferIn = input; | ||
} else if (typeof input === 'undefined' || input === null) { | ||
} else if (!isDefined(input)) { | ||
// input=stream | ||
@@ -156,2 +162,8 @@ this.options.streamIn = true; | ||
}; | ||
var isBuffer = function(val) { | ||
return typeof val === 'object' && val instanceof Buffer; | ||
}; | ||
var isString = function(val) { | ||
return typeof val === 'string' && val.length > 0; | ||
}; | ||
var isInteger = function(val) { | ||
@@ -163,2 +175,5 @@ return typeof val === 'number' && !Number.isNaN(val) && val % 1 === 0; | ||
}; | ||
var contains = function(val, list) { | ||
return list.indexOf(val) !== -1; | ||
}; | ||
@@ -174,3 +189,3 @@ /* | ||
if (isInteger(options.density) && inRange(options.density, 1, 2400)) { | ||
this.options.density = options.density.toString(); | ||
this.options.density = options.density; | ||
} else { | ||
@@ -227,26 +242,40 @@ throw new Error('Invalid density (1 to 2400) ' + options.density); | ||
// Crop this part of the resized image (Center/Centre, North, East, South, West) | ||
// Weighting to apply to image crop | ||
module.exports.gravity = { | ||
'center': 0, | ||
'centre': 0, | ||
'north': 1, | ||
'east': 2, | ||
'south': 3, | ||
'west': 4, | ||
'northeast': 5, | ||
'southeast': 6, | ||
'southwest': 7, | ||
'northwest': 8 | ||
center: 0, | ||
centre: 0, | ||
north: 1, | ||
east: 2, | ||
south: 3, | ||
west: 4, | ||
northeast: 5, | ||
southeast: 6, | ||
southwest: 7, | ||
northwest: 8 | ||
}; | ||
Sharp.prototype.crop = function(gravity) { | ||
// Strategies for automagic behaviour | ||
module.exports.strategy = { | ||
entropy: 16 | ||
}; | ||
/* | ||
What part of the image should be retained when cropping? | ||
*/ | ||
Sharp.prototype.crop = function(crop) { | ||
this.options.canvas = 'crop'; | ||
if (typeof gravity === 'undefined') { | ||
this.options.gravity = module.exports.gravity.center; | ||
} else if (typeof gravity === 'number' && !Number.isNaN(gravity) && gravity >= 0 && gravity <= 8) { | ||
this.options.gravity = gravity; | ||
} else if (typeof gravity === 'string' && typeof module.exports.gravity[gravity] === 'number') { | ||
this.options.gravity = module.exports.gravity[gravity]; | ||
if (!isDefined(crop)) { | ||
// Default | ||
this.options.crop = module.exports.gravity.center; | ||
} else if (isInteger(crop) && inRange(crop, 0, 8)) { | ||
// Gravity (numeric) | ||
this.options.crop = crop; | ||
} else if (isString(crop) && isInteger(module.exports.gravity[crop])) { | ||
// Gravity (string) | ||
this.options.crop = module.exports.gravity[crop]; | ||
} else if (isInteger(crop) && crop === module.exports.strategy.entropy) { | ||
// Strategy | ||
this.options.crop = crop; | ||
} else { | ||
throw new Error('Unsupported crop gravity ' + gravity); | ||
throw new Error('Unsupported crop ' + crop); | ||
} | ||
@@ -257,15 +286,6 @@ return this; | ||
Sharp.prototype.extract = function(options) { | ||
if (!options || typeof options !== 'object') { | ||
// Legacy extract(top,left,width,height) syntax | ||
options = { | ||
left: arguments[1], | ||
top: arguments[0], | ||
width: arguments[2], | ||
height: arguments[3] | ||
}; | ||
} | ||
var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post'; | ||
['left', 'top', 'width', 'height'].forEach(function (name) { | ||
var value = options[name]; | ||
if (typeof value === 'number' && !Number.isNaN(value) && value % 1 === 0 && value >= 0) { | ||
if (isInteger(value) && value >= 0) { | ||
this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value; | ||
@@ -329,10 +349,22 @@ } else { | ||
Sharp.prototype.overlayWith = function(overlayPath) { | ||
if (typeof overlayPath !== 'string') { | ||
throw new Error('The overlay path must be a string'); | ||
/* | ||
Overlay with another image, using an optional gravity | ||
*/ | ||
Sharp.prototype.overlayWith = function(overlay, options) { | ||
if (isString(overlay)) { | ||
this.options.overlayFileIn = overlay; | ||
} else if (isBuffer(overlay)) { | ||
this.options.overlayBufferIn = overlay; | ||
} else { | ||
throw new Error('Unsupported overlay ' + typeof overlay); | ||
} | ||
if (overlayPath === '') { | ||
throw new Error('The overlay path cannot be empty'); | ||
if (isObject(options)) { | ||
if (isInteger(options.gravity) && inRange(options.gravity, 0, 8)) { | ||
this.options.overlayGravity = options.gravity; | ||
} else if (isString(options.gravity) && isInteger(module.exports.gravity[options.gravity])) { | ||
this.options.overlayGravity = module.exports.gravity[options.gravity]; | ||
} else if (isDefined(options.gravity)) { | ||
throw new Error('Unsupported overlay gravity ' + options.gravity); | ||
} | ||
} | ||
this.options.overlayPath = overlayPath; | ||
return this; | ||
@@ -606,8 +638,8 @@ }; | ||
withMetadata.orientation % 1 === 0 && | ||
withMetadata.orientation >= 0 && | ||
withMetadata.orientation <= 7 | ||
withMetadata.orientation >= 1 && | ||
withMetadata.orientation <= 8 | ||
) { | ||
this.options.withMetadataOrientation = withMetadata.orientation; | ||
} else { | ||
throw new Error('Invalid orientation (0 to 7) ' + withMetadata.orientation); | ||
throw new Error('Invalid orientation (1 to 8) ' + withMetadata.orientation); | ||
} | ||
@@ -620,23 +652,33 @@ } | ||
/* | ||
Tile size and overlap for Deep Zoom output | ||
Tile-based deep zoom output options: size, overlap, layout | ||
*/ | ||
Sharp.prototype.tile = function(size, overlap) { | ||
// Size of square tiles, in pixels | ||
if (typeof size !== 'undefined' && size !== null) { | ||
if (!Number.isNaN(size) && size % 1 === 0 && size >= 1 && size <= 8192) { | ||
this.options.tileSize = size; | ||
} else { | ||
throw new Error('Invalid tile size (1 to 8192) ' + size); | ||
Sharp.prototype.tile = function(tile) { | ||
if (isObject(tile)) { | ||
// Size of square tiles, in pixels | ||
if (isDefined(tile.size)) { | ||
if (isInteger(tile.size) && inRange(tile.size, 1, 8192)) { | ||
this.options.tileSize = tile.size; | ||
} else { | ||
throw new Error('Invalid tile size (1 to 8192) ' + tile.size); | ||
} | ||
} | ||
} | ||
// Overlap of tiles, in pixels | ||
if (typeof overlap !== 'undefined' && overlap !== null) { | ||
if (!Number.isNaN(overlap) && overlap % 1 === 0 && overlap >= 0 && overlap <= 8192) { | ||
if (overlap > this.options.tileSize) { | ||
throw new Error('Tile overlap ' + overlap + ' cannot be larger than tile size ' + this.options.tileSize); | ||
// Overlap of tiles, in pixels | ||
if (isDefined(tile.overlap)) { | ||
if (isInteger(tile.overlap) && inRange(tile.overlap, 0, 8192)) { | ||
if (tile.overlap > this.options.tileSize) { | ||
throw new Error('Tile overlap ' + tile.overlap + ' cannot be larger than tile size ' + this.options.tileSize); | ||
} | ||
this.options.tileOverlap = tile.overlap; | ||
} else { | ||
throw new Error('Invalid tile overlap (0 to 8192) ' + tile.overlap); | ||
} | ||
this.options.tileOverlap = overlap; | ||
} else { | ||
throw new Error('Invalid tile overlap (0 to 8192) ' + overlap); | ||
} | ||
// Layout | ||
if (isDefined(tile.layout)) { | ||
if (isString(tile.layout) && contains(tile.layout, ['dz', 'google', 'zoomify'])) { | ||
this.options.tileLayout = tile.layout; | ||
} else { | ||
throw new Error('Invalid tile layout ' + tile.layout); | ||
} | ||
} | ||
} | ||
@@ -646,2 +688,28 @@ return this; | ||
/* | ||
Extend edges | ||
*/ | ||
Sharp.prototype.extend = function(extend) { | ||
if (isInteger(extend) && extend > 0) { | ||
this.options.extendTop = extend; | ||
this.options.extendBottom = extend; | ||
this.options.extendLeft = extend; | ||
this.options.extendRight = extend; | ||
} else if ( | ||
isObject(extend) && | ||
isInteger(extend.top) && extend.top >= 0 && | ||
isInteger(extend.bottom) && extend.bottom >= 0 && | ||
isInteger(extend.left) && extend.left >= 0 && | ||
isInteger(extend.right) && extend.right >= 0 | ||
) { | ||
this.options.extendTop = extend.top; | ||
this.options.extendBottom = extend.bottom; | ||
this.options.extendLeft = extend.left; | ||
this.options.extendRight = extend.right; | ||
} else { | ||
throw new Error('Invalid edge extension ' + extend); | ||
} | ||
return this; | ||
}; | ||
Sharp.prototype.resize = function(width, height) { | ||
@@ -800,6 +868,7 @@ if (!width) { | ||
this.on('finish', function() { | ||
sharp.pipeline(that.options, function(err, data) { | ||
sharp.pipeline(that.options, function(err, data, info) { | ||
if (err) { | ||
that.emit('error', err); | ||
} else { | ||
that.emit('info', info); | ||
that.push(data); | ||
@@ -812,6 +881,7 @@ } | ||
// output=stream, input=file/buffer | ||
sharp.pipeline(this.options, function(err, data) { | ||
sharp.pipeline(this.options, function(err, data, info) { | ||
if (err) { | ||
that.emit('error', err); | ||
} else { | ||
that.emit('info', info); | ||
that.push(data); | ||
@@ -818,0 +888,0 @@ } |
{ | ||
"name": "sharp", | ||
"version": "0.13.1", | ||
"version": "0.14.0", | ||
"author": "Lovell Fuller <npm@lovell.info>", | ||
@@ -21,3 +21,4 @@ "contributors": [ | ||
"Chris Riley <criley@primedia.com>", | ||
"David Carley <dacarley@gmail.com>" | ||
"David Carley <dacarley@gmail.com>", | ||
"John Tobin <john@limelightmobileinc.com>" | ||
], | ||
@@ -51,5 +52,5 @@ "description": "High performance Node.js module to resize JPEG, PNG, WebP and TIFF images using the libvips library", | ||
"dependencies": { | ||
"bluebird": "^3.3.3", | ||
"bluebird": "^3.3.4", | ||
"color": "^0.11.1", | ||
"nan": "^2.2.0", | ||
"nan": "^2.2.1", | ||
"semver": "^5.1.0", | ||
@@ -61,3 +62,3 @@ "request": "^2.69.0", | ||
"async": "^1.5.2", | ||
"coveralls": "^2.11.8", | ||
"coveralls": "^2.11.9", | ||
"exif-reader": "^1.0.0", | ||
@@ -74,3 +75,3 @@ "icc": "^0.0.2", | ||
"config": { | ||
"libvips": "8.2.2" | ||
"libvips": "8.2.3" | ||
}, | ||
@@ -77,0 +78,0 @@ "engines": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
845390
1068
Updatedbluebird@^3.3.4
Updatednan@^2.2.1