sharp 0.32.6 → 0.33.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  <img src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
4
4
 
5
- The typical use case for this high speed Node.js module
5
+ The typical use case for this high speed Node-API module
6
6
  is to convert large images in common formats to
7
7
  smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions.
8
8
 
9
+ It can be used with all JavaScript runtimes
10
+ that provide support for Node-API v9, including
11
+ Node.js (^18.17.0 or >= 20.3.0), Deno and Bun.
12
+
9
13
  Resizing an image is typically 4x-5x faster than using the
10
14
  quickest ImageMagick and GraphicsMagick settings
11
15
  due to its use of [libvips](https://github.com/libvips/libvips).
@@ -16,7 +20,7 @@ Lanczos resampling ensures quality is not sacrificed for speed.
16
20
  As well as image resizing, operations such as
17
21
  rotation, extraction, compositing and gamma correction are available.
18
22
 
19
- Most modern macOS, Windows and Linux systems running Node.js >= 14.15.0
23
+ Most modern macOS, Windows and Linux systems
20
24
  do not require any additional install or runtime dependencies.
21
25
 
22
26
  ## Documentation
@@ -0,0 +1,41 @@
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ 'use strict';
5
+
6
+ try {
7
+ const { useGlobalLibvips, globalLibvipsVersion, log, spawnRebuild } = require('../lib/libvips');
8
+
9
+ const buildFromSource = (msg) => {
10
+ log(msg);
11
+ log('Attempting to build from source via node-gyp');
12
+ try {
13
+ const addonApi = require('node-addon-api');
14
+ log(`Found node-addon-api ${addonApi.version || ''}`);
15
+ } catch (err) {
16
+ log('Please add node-addon-api to your dependencies');
17
+ return;
18
+ }
19
+ try {
20
+ const gyp = require('node-gyp');
21
+ log(`Found node-gyp version ${gyp().version}`);
22
+ } catch (err) {
23
+ log('Please add node-gyp to your dependencies');
24
+ return;
25
+ }
26
+ log('See https://sharp.pixelplumbing.com/install#building-from-source');
27
+ const status = spawnRebuild();
28
+ if (status !== 0) {
29
+ process.exit(status);
30
+ }
31
+ };
32
+
33
+ if (useGlobalLibvips()) {
34
+ buildFromSource(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
35
+ } else if (process.env.npm_config_build_from_source) {
36
+ buildFromSource('Detected --build-from-source flag');
37
+ }
38
+ } catch (err) {
39
+ const summary = err.message.split(/\n/).slice(0, 1);
40
+ console.log(`sharp: skipping install check: ${summary}`);
41
+ }
package/lib/colour.js CHANGED
@@ -19,7 +19,7 @@ const colourspace = {
19
19
  };
20
20
 
21
21
  /**
22
- * Tint the image using the provided chroma while preserving the image luminance.
22
+ * Tint the image using the provided colour.
23
23
  * An alpha channel may be present and will be unchanged by the operation.
24
24
  *
25
25
  * @example
@@ -27,14 +27,12 @@ const colourspace = {
27
27
  * .tint({ r: 255, g: 240, b: 16 })
28
28
  * .toBuffer();
29
29
  *
30
- * @param {string|Object} rgb - parsed by the [color](https://www.npmjs.org/package/color) module to extract chroma values.
30
+ * @param {string|Object} tint - Parsed by the [color](https://www.npmjs.org/package/color) module.
31
31
  * @returns {Sharp}
32
32
  * @throws {Error} Invalid parameter
33
33
  */
34
- function tint (rgb) {
35
- const colour = color(rgb);
36
- this.options.tintA = colour.a();
37
- this.options.tintB = colour.b();
34
+ function tint (tint) {
35
+ this._setBackgroundColourOption('tint', tint);
38
36
  return this;
39
37
  }
40
38
 
@@ -73,8 +71,6 @@ function grayscale (grayscale) {
73
71
  * All operations will use this colourspace before converting to the output colourspace,
74
72
  * as defined by {@link #tocolourspace|toColourspace}.
75
73
  *
76
- * This feature is experimental and has not yet been fully-tested with all operations.
77
- *
78
74
  * @since 0.29.0
79
75
  *
80
76
  * @example
@@ -92,7 +88,7 @@ function pipelineColourspace (colourspace) {
92
88
  if (!is.string(colourspace)) {
93
89
  throw is.invalidParameterError('colourspace', 'string', colourspace);
94
90
  }
95
- this.options.colourspaceInput = colourspace;
91
+ this.options.colourspacePipeline = colourspace;
96
92
  return this;
97
93
  }
98
94
 
@@ -3,11 +3,10 @@
3
3
 
4
4
  'use strict';
5
5
 
6
- const util = require('util');
7
- const stream = require('stream');
6
+ const util = require('node:util');
7
+ const stream = require('node:stream');
8
8
  const is = require('./is');
9
9
 
10
- require('./libvips').hasVendoredLibvips();
11
10
  require('./sharp');
12
11
 
13
12
  // Use NODE_DEBUG=sharp to enable libvips warnings
@@ -23,6 +22,10 @@ const debuglog = util.debuglog('sharp');
23
22
  *
24
23
  * Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
25
24
  *
25
+ * When loading more than one page/frame of an animated image,
26
+ * these are combined as a vertically-stacked "toilet roll" image
27
+ * where the overall height is the `pageHeight` multiplied by the number of `pages`.
28
+ *
26
29
  * @constructs Sharp
27
30
  *
28
31
  * @emits Sharp#info
@@ -37,14 +40,16 @@ const debuglog = util.debuglog('sharp');
37
40
  * });
38
41
  *
39
42
  * @example
40
- * // Read image data from readableStream,
43
+ * // Read image data from remote URL,
41
44
  * // resize to 300 pixels wide,
42
45
  * // emit an 'info' event with calculated dimensions
43
46
  * // and finally write image data to writableStream
44
- * var transformer = sharp()
47
+ * const { body } = fetch('https://...');
48
+ * const readableStream = Readable.fromWeb(body);
49
+ * const transformer = sharp()
45
50
  * .resize(300)
46
- * .on('info', function(info) {
47
- * console.log('Image height is ' + info.height);
51
+ * .on('info', ({ height }) => {
52
+ * console.log(`Image height is ${height}`);
48
53
  * });
49
54
  * readableStream.pipe(transformer).pipe(writableStream);
50
55
  *
@@ -122,7 +127,7 @@ const debuglog = util.debuglog('sharp');
122
127
  * a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
123
128
  * JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
124
129
  * @param {Object} [options] - if present, is an Object with optional attributes.
125
- * @param {string} [options.failOn='warning'] - when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), higher levels imply lower levels, invalid metadata will always abort.
130
+ * @param {string} [options.failOn='warning'] - When to abort processing of invalid pixel data, one of (in order of sensitivity, least to most): 'none', 'truncated', 'error', 'warning'. Higher levels imply lower levels. Invalid metadata will always abort.
126
131
  * @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
127
132
  * (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
128
133
  * An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
@@ -161,7 +166,7 @@ const debuglog = util.debuglog('sharp');
161
166
  * @param {number} [options.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
162
167
  * @param {boolean} [options.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
163
168
  * @param {number} [options.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
164
- * @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none'.
169
+ * @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'.
165
170
  * @returns {Sharp}
166
171
  * @throws {Error} Invalid parameters
167
172
  */
@@ -213,8 +218,7 @@ const Sharp = function (input, options) {
213
218
  kernel: 'lanczos3',
214
219
  fastShrinkOnLoad: true,
215
220
  // operations
216
- tintA: 128,
217
- tintB: 128,
221
+ tint: [-1, 0, 0, 0],
218
222
  flatten: false,
219
223
  flattenBackground: [0, 0, 0],
220
224
  unflatten: false,
@@ -231,7 +235,8 @@ const Sharp = function (input, options) {
231
235
  threshold: 0,
232
236
  thresholdGrayscale: true,
233
237
  trimBackground: [],
234
- trimThreshold: 0,
238
+ trimThreshold: -1,
239
+ trimLineArt: false,
235
240
  gamma: 0,
236
241
  gammaOut: 0,
237
242
  greyscale: false,
@@ -252,17 +257,18 @@ const Sharp = function (input, options) {
252
257
  removeAlpha: false,
253
258
  ensureAlpha: -1,
254
259
  colourspace: 'srgb',
255
- colourspaceInput: 'last',
260
+ colourspacePipeline: 'last',
256
261
  composite: [],
257
262
  // output
258
263
  fileOut: '',
259
264
  formatOut: 'input',
260
265
  streamOut: false,
261
- withMetadata: false,
266
+ keepMetadata: 0,
262
267
  withMetadataOrientation: -1,
263
268
  withMetadataDensity: 0,
264
- withMetadataIcc: '',
265
- withMetadataStrs: {},
269
+ withIccProfile: '',
270
+ withExif: {},
271
+ withExifMerge: true,
266
272
  resolveWithObject: false,
267
273
  // output format
268
274
  jpegQuality: 80,
@@ -306,6 +312,7 @@ const Sharp = function (input, options) {
306
312
  tiffCompression: 'jpeg',
307
313
  tiffPredictor: 'horizontal',
308
314
  tiffPyramid: false,
315
+ tiffMiniswhite: false,
309
316
  tiffBitdepth: 8,
310
317
  tiffTile: false,
311
318
  tiffTileHeight: 256,
@@ -318,6 +325,7 @@ const Sharp = function (input, options) {
318
325
  heifCompression: 'av1',
319
326
  heifEffort: 4,
320
327
  heifChromaSubsampling: '4:4:4',
328
+ heifBitdepth: 8,
321
329
  jxlDistance: 1,
322
330
  jxlDecodingTier: 0,
323
331
  jxlEffort: 7,
@@ -418,13 +426,16 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
418
426
  function clone () {
419
427
  // Clone existing options
420
428
  const clone = this.constructor.call();
421
- clone.options = Object.assign({}, this.options);
429
+ const { debuglog, queueListener, ...options } = this.options;
430
+ clone.options = structuredClone(options);
431
+ clone.options.debuglog = debuglog;
432
+ clone.options.queueListener = queueListener;
422
433
  // Pass 'finish' event to clone for Stream-based input
423
434
  if (this._isStreamInput()) {
424
435
  this.on('finish', () => {
425
436
  // Clone inherits input data
426
437
  this._flattenBufferIn();
427
- clone.options.bufferIn = this.options.bufferIn;
438
+ clone.options.input.buffer = this.options.input.buffer;
428
439
  clone.emit('finish');
429
440
  });
430
441
  }
package/lib/index.d.ts CHANGED
@@ -91,12 +91,6 @@ declare namespace sharp {
91
91
  zlib?: string | undefined;
92
92
  };
93
93
 
94
- /** An Object containing the platform and architecture of the current and installed vendored binaries. */
95
- const vendor: {
96
- current: string;
97
- installed: string[];
98
- };
99
-
100
94
  /** An Object containing the available interpolators and their proper values */
101
95
  const interpolators: Interpolators;
102
96
 
@@ -132,7 +126,7 @@ declare namespace sharp {
132
126
  function counters(): SharpCounters;
133
127
 
134
128
  /**
135
- * Get and set use of SIMD vector unit instructions. Requires libvips to have been compiled with liborc support.
129
+ * Get and set use of SIMD vector unit instructions. Requires libvips to have been compiled with highway support.
136
130
  * Improves the performance of resize, blur and sharpen operations by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
137
131
  * @param enable enable or disable use of SIMD vector unit instructions
138
132
  * @returns true if usage of SIMD vector unit instructions is enabled
@@ -245,12 +239,12 @@ declare namespace sharp {
245
239
  //#region Color functions
246
240
 
247
241
  /**
248
- * Tint the image using the provided chroma while preserving the image luminance.
242
+ * Tint the image using the provided colour.
249
243
  * An alpha channel may be present and will be unchanged by the operation.
250
- * @param rgb Parsed by the color module to extract chroma values.
244
+ * @param tint Parsed by the color module.
251
245
  * @returns A sharp instance that can be used to chain operations
252
246
  */
253
- tint(rgb: Color): Sharp;
247
+ tint(tint: Color): Sharp;
254
248
 
255
249
  /**
256
250
  * Convert to 8-bit greyscale; 256 shades of grey.
@@ -347,6 +341,12 @@ declare namespace sharp {
347
341
  */
348
342
  metadata(): Promise<Metadata>;
349
343
 
344
+ /**
345
+ * Keep all metadata (EXIF, ICC, XMP, IPTC) from the input image in the output image.
346
+ * @returns A sharp instance that can be used to chain operations
347
+ */
348
+ keepMetadata(): Sharp;
349
+
350
350
  /**
351
351
  * Access to pixel-derived image statistics for every channel in the image.
352
352
  * @returns A sharp instance that can be used to chain operations
@@ -639,6 +639,43 @@ declare namespace sharp {
639
639
  */
640
640
  toBuffer(options: { resolveWithObject: true }): Promise<{ data: Buffer; info: OutputInfo }>;
641
641
 
642
+ /**
643
+ * Keep all EXIF metadata from the input image in the output image.
644
+ * EXIF metadata is unsupported for TIFF output.
645
+ * @returns A sharp instance that can be used to chain operations
646
+ */
647
+ keepExif(): Sharp;
648
+
649
+ /**
650
+ * Set EXIF metadata in the output image, ignoring any EXIF in the input image.
651
+ * @param {Exif} exif Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
652
+ * @returns A sharp instance that can be used to chain operations
653
+ * @throws {Error} Invalid parameters
654
+ */
655
+ withExif(exif: Exif): Sharp;
656
+
657
+ /**
658
+ * Update EXIF metadata from the input image in the output image.
659
+ * @param {Exif} exif Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
660
+ * @returns A sharp instance that can be used to chain operations
661
+ * @throws {Error} Invalid parameters
662
+ */
663
+ withExifMerge(exif: Exif): Sharp;
664
+
665
+ /**
666
+ * Keep ICC profile from the input image in the output image where possible.
667
+ * @returns A sharp instance that can be used to chain operations
668
+ */
669
+ keepIccProfile(): Sharp;
670
+
671
+ /**
672
+ * Transform using an ICC profile and attach to the output image.
673
+ * @param {string} icc - Absolute filesystem path to output ICC profile or built-in profile name (srgb, p3, cmyk).
674
+ * @returns A sharp instance that can be used to chain operations
675
+ * @throws {Error} Invalid parameters
676
+ */
677
+ withIccProfile(icc: string, options?: WithIccProfileOptions): Sharp;
678
+
642
679
  /**
643
680
  * Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
644
681
  * The default behaviour, when withMetadata is not used, is to strip all metadata and convert to the device-independent sRGB colour space.
@@ -705,7 +742,6 @@ declare namespace sharp {
705
742
 
706
743
  /**
707
744
  * Use these AVIF options for output image.
708
- * Whilst it is possible to create AVIF images smaller than 16x16 pixels, most web browsers do not display these properly.
709
745
  * @param options Output options.
710
746
  * @throws {Error} Invalid options
711
747
  * @returns A sharp instance that can be used to chain operations
@@ -854,11 +890,11 @@ declare namespace sharp {
854
890
  * Trim pixels from all edges that contain values similar to the given background colour, which defaults to that of the top-left pixel.
855
891
  * Images with an alpha channel will use the combined bounding box of alpha and non-alpha channels.
856
892
  * The info response Object will contain trimOffsetLeft and trimOffsetTop properties.
857
- * @param trim The specific background colour to trim, the threshold for doing so or an Object with both.
893
+ * @param options trim options
858
894
  * @throws {Error} Invalid parameters
859
895
  * @returns A sharp instance that can be used to chain operations
860
896
  */
861
- trim(trim?: string | number | TrimOptions): Sharp;
897
+ trim(options?: TrimOptions): Sharp;
862
898
 
863
899
  //#endregion
864
900
  }
@@ -981,19 +1017,36 @@ declare namespace sharp {
981
1017
  rgba?: boolean;
982
1018
  /** Text line height in points. Will use the font line height if none is specified. (optional, default `0`) */
983
1019
  spacing?: number;
984
- /** Word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none' */
1020
+ /** Word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none' */
985
1021
  wrap?: TextWrap;
986
1022
  }
987
1023
 
1024
+ interface ExifDir {
1025
+ [k: string]: string;
1026
+ }
1027
+
1028
+ interface Exif {
1029
+ 'IFD0'?: ExifDir;
1030
+ 'IFD1'?: ExifDir;
1031
+ 'IFD2'?: ExifDir;
1032
+ 'IFD3'?: ExifDir;
1033
+ }
1034
+
988
1035
  interface WriteableMetadata {
1036
+ /** Number of pixels per inch (DPI) */
1037
+ density?: number | undefined;
989
1038
  /** Value between 1 and 8, used to update the EXIF Orientation tag. */
990
1039
  orientation?: number | undefined;
991
- /** Filesystem path to output ICC profile, defaults to sRGB. */
1040
+ /**
1041
+ * Filesystem path to output ICC profile, defaults to sRGB.
1042
+ * @deprecated Use `withIccProfile()` instead.
1043
+ */
992
1044
  icc?: string | undefined;
993
- /** Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data. (optional, default {}) */
994
- exif?: Record<string, any> | undefined;
995
- /** Number of pixels per inch (DPI) */
996
- density?: number | undefined;
1045
+ /**
1046
+ * Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
1047
+ * @deprecated Use `withExif()` or `withExifMerge()` instead.
1048
+ */
1049
+ exif?: Exif | undefined;
997
1050
  }
998
1051
 
999
1052
  interface Metadata {
@@ -1103,6 +1156,11 @@ declare namespace sharp {
1103
1156
  force?: boolean | undefined;
1104
1157
  }
1105
1158
 
1159
+ interface WithIccProfileOptions {
1160
+ /** Should the ICC profile be included in the output image metadata? (optional, default true) */
1161
+ attach?: boolean | undefined;
1162
+ }
1163
+
1106
1164
  interface JpegOptions extends OutputOptions {
1107
1165
  /** Quality, integer 1-100 (optional, default 80) */
1108
1166
  quality?: number | undefined;
@@ -1186,6 +1244,8 @@ declare namespace sharp {
1186
1244
  effort?: number | undefined;
1187
1245
  /** set to '4:2:0' to use chroma subsampling, requires libvips v8.11.0 (optional, default '4:4:4') */
1188
1246
  chromaSubsampling?: string | undefined;
1247
+ /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1248
+ bitdepth?: 8 | 10 | 12 | undefined;
1189
1249
  }
1190
1250
 
1191
1251
  interface HeifOptions extends OutputOptions {
@@ -1199,6 +1259,8 @@ declare namespace sharp {
1199
1259
  effort?: number | undefined;
1200
1260
  /** set to '4:2:0' to use chroma subsampling (optional, default '4:4:4') */
1201
1261
  chromaSubsampling?: string | undefined;
1262
+ /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1263
+ bitdepth?: 8 | 10 | 12 | undefined;
1202
1264
  }
1203
1265
 
1204
1266
  interface GifOptions extends OutputOptions, AnimationOptions {
@@ -1241,6 +1303,8 @@ declare namespace sharp {
1241
1303
  yres?: number | undefined;
1242
1304
  /** Reduce bitdepth to 1, 2 or 4 bit (optional, default 8) */
1243
1305
  bitdepth?: 1 | 2 | 4 | 8 | undefined;
1306
+ /** Write 1-bit images as miniswhite (optional, default false) */
1307
+ miniswhite?: boolean | undefined;
1244
1308
  /** Resolution unit options: inch, cm (optional, default 'inch') */
1245
1309
  resolutionUnit?: 'inch' | 'cm' | undefined;
1246
1310
  }
@@ -1282,10 +1346,10 @@ declare namespace sharp {
1282
1346
  }
1283
1347
 
1284
1348
  interface NormaliseOptions {
1285
- /** Percentile below which luminance values will be underexposed. */
1286
- lower?: number | undefined;
1287
- /** Percentile above which luminance values will be overexposed. */
1288
- upper?: number | undefined;
1349
+ /** Percentile below which luminance values will be underexposed. */
1350
+ lower?: number | undefined;
1351
+ /** Percentile above which luminance values will be overexposed. */
1352
+ upper?: number | undefined;
1289
1353
  }
1290
1354
 
1291
1355
  interface ResizeOptions {
@@ -1347,10 +1411,12 @@ declare namespace sharp {
1347
1411
  }
1348
1412
 
1349
1413
  interface TrimOptions {
1350
- /** background colour, parsed by the color module, defaults to that of the top-left pixel. (optional) */
1414
+ /** Background colour, parsed by the color module, defaults to that of the top-left pixel. (optional) */
1351
1415
  background?: Color | undefined;
1352
- /** the allowed difference from the above colour, a positive number. (optional, default `10`) */
1416
+ /** Allowed difference from the above colour, a positive number. (optional, default 10) */
1353
1417
  threshold?: number | undefined;
1418
+ /** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
1419
+ lineArt?: boolean | undefined;
1354
1420
  }
1355
1421
 
1356
1422
  interface RawOptions {
@@ -1413,6 +1479,14 @@ declare namespace sharp {
1413
1479
  tile?: boolean | undefined;
1414
1480
  /** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
1415
1481
  premultiplied?: boolean | undefined;
1482
+ /** number representing the DPI for vector overlay image. (optional, default 72)*/
1483
+ density?: number | undefined;
1484
+ /** Set to true to read all frames/pages of an animated image. (optional, default false) */
1485
+ animated?: boolean | undefined;
1486
+ /** see sharp() constructor, (optional, default 'warning') */
1487
+ failOn?: FailOnOptions | undefined;
1488
+ /** see sharp() constructor, (optional, default 268402689) */
1489
+ limitInputPixels?: number | boolean | undefined;
1416
1490
  }
1417
1491
 
1418
1492
  interface TileOptions {
@@ -1551,7 +1625,7 @@ declare namespace sharp {
1551
1625
 
1552
1626
  type TextAlign = 'left' | 'centre' | 'center' | 'right';
1553
1627
 
1554
- type TextWrap = 'word' | 'char' | 'charWord' | 'none';
1628
+ type TextWrap = 'word' | 'char' | 'word-char' | 'none';
1555
1629
 
1556
1630
  type TileContainer = 'fs' | 'zip';
1557
1631
 
package/lib/input.js CHANGED
@@ -296,17 +296,17 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
296
296
  }
297
297
  }
298
298
  if (is.defined(inputOptions.text.width)) {
299
- if (is.number(inputOptions.text.width)) {
299
+ if (is.integer(inputOptions.text.width) && inputOptions.text.width > 0) {
300
300
  inputDescriptor.textWidth = inputOptions.text.width;
301
301
  } else {
302
- throw is.invalidParameterError('text.textWidth', 'number', inputOptions.text.width);
302
+ throw is.invalidParameterError('text.width', 'positive integer', inputOptions.text.width);
303
303
  }
304
304
  }
305
305
  if (is.defined(inputOptions.text.height)) {
306
- if (is.number(inputOptions.text.height)) {
306
+ if (is.integer(inputOptions.text.height) && inputOptions.text.height > 0) {
307
307
  inputDescriptor.textHeight = inputOptions.text.height;
308
308
  } else {
309
- throw is.invalidParameterError('text.height', 'number', inputOptions.text.height);
309
+ throw is.invalidParameterError('text.height', 'positive integer', inputOptions.text.height);
310
310
  }
311
311
  }
312
312
  if (is.defined(inputOptions.text.align)) {
@@ -324,10 +324,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
324
324
  }
325
325
  }
326
326
  if (is.defined(inputOptions.text.dpi)) {
327
- if (is.number(inputOptions.text.dpi) && is.inRange(inputOptions.text.dpi, 1, 100000)) {
327
+ if (is.integer(inputOptions.text.dpi) && is.inRange(inputOptions.text.dpi, 1, 1000000)) {
328
328
  inputDescriptor.textDpi = inputOptions.text.dpi;
329
329
  } else {
330
- throw is.invalidParameterError('text.dpi', 'number between 1 and 100000', inputOptions.text.dpi);
330
+ throw is.invalidParameterError('text.dpi', 'integer between 1 and 1000000', inputOptions.text.dpi);
331
331
  }
332
332
  }
333
333
  if (is.defined(inputOptions.text.rgba)) {
@@ -338,17 +338,17 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
338
338
  }
339
339
  }
340
340
  if (is.defined(inputOptions.text.spacing)) {
341
- if (is.number(inputOptions.text.spacing)) {
341
+ if (is.integer(inputOptions.text.spacing) && is.inRange(inputOptions.text.spacing, -1000000, 1000000)) {
342
342
  inputDescriptor.textSpacing = inputOptions.text.spacing;
343
343
  } else {
344
- throw is.invalidParameterError('text.spacing', 'number', inputOptions.text.spacing);
344
+ throw is.invalidParameterError('text.spacing', 'integer between -1000000 and 1000000', inputOptions.text.spacing);
345
345
  }
346
346
  }
347
347
  if (is.defined(inputOptions.text.wrap)) {
348
- if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'wordChar', 'none'])) {
348
+ if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'word-char', 'none'])) {
349
349
  inputDescriptor.textWrap = inputOptions.text.wrap;
350
350
  } else {
351
- throw is.invalidParameterError('text.wrap', 'one of: word, char, wordChar, none', inputOptions.text.wrap);
351
+ throw is.invalidParameterError('text.wrap', 'one of: word, char, word-char, none', inputOptions.text.wrap);
352
352
  }
353
353
  }
354
354
  delete inputDescriptor.buffer;
@@ -483,14 +483,27 @@ function _isStreamInput () {
483
483
  * @returns {Promise<Object>|Sharp}
484
484
  */
485
485
  function metadata (callback) {
486
+ const stack = Error();
486
487
  if (is.fn(callback)) {
487
488
  if (this._isStreamInput()) {
488
489
  this.on('finish', () => {
489
490
  this._flattenBufferIn();
490
- sharp.metadata(this.options, callback);
491
+ sharp.metadata(this.options, (err, metadata) => {
492
+ if (err) {
493
+ callback(is.nativeError(err, stack));
494
+ } else {
495
+ callback(null, metadata);
496
+ }
497
+ });
491
498
  });
492
499
  } else {
493
- sharp.metadata(this.options, callback);
500
+ sharp.metadata(this.options, (err, metadata) => {
501
+ if (err) {
502
+ callback(is.nativeError(err, stack));
503
+ } else {
504
+ callback(null, metadata);
505
+ }
506
+ });
494
507
  }
495
508
  return this;
496
509
  } else {
@@ -500,7 +513,7 @@ function metadata (callback) {
500
513
  this._flattenBufferIn();
501
514
  sharp.metadata(this.options, (err, metadata) => {
502
515
  if (err) {
503
- reject(err);
516
+ reject(is.nativeError(err, stack));
504
517
  } else {
505
518
  resolve(metadata);
506
519
  }
@@ -516,7 +529,7 @@ function metadata (callback) {
516
529
  return new Promise((resolve, reject) => {
517
530
  sharp.metadata(this.options, (err, metadata) => {
518
531
  if (err) {
519
- reject(err);
532
+ reject(is.nativeError(err, stack));
520
533
  } else {
521
534
  resolve(metadata);
522
535
  }
@@ -572,14 +585,27 @@ function metadata (callback) {
572
585
  * @returns {Promise<Object>}
573
586
  */
574
587
  function stats (callback) {
588
+ const stack = Error();
575
589
  if (is.fn(callback)) {
576
590
  if (this._isStreamInput()) {
577
591
  this.on('finish', () => {
578
592
  this._flattenBufferIn();
579
- sharp.stats(this.options, callback);
593
+ sharp.stats(this.options, (err, stats) => {
594
+ if (err) {
595
+ callback(is.nativeError(err, stack));
596
+ } else {
597
+ callback(null, stats);
598
+ }
599
+ });
580
600
  });
581
601
  } else {
582
- sharp.stats(this.options, callback);
602
+ sharp.stats(this.options, (err, stats) => {
603
+ if (err) {
604
+ callback(is.nativeError(err, stack));
605
+ } else {
606
+ callback(null, stats);
607
+ }
608
+ });
583
609
  }
584
610
  return this;
585
611
  } else {
@@ -589,7 +615,7 @@ function stats (callback) {
589
615
  this._flattenBufferIn();
590
616
  sharp.stats(this.options, (err, stats) => {
591
617
  if (err) {
592
- reject(err);
618
+ reject(is.nativeError(err, stack));
593
619
  } else {
594
620
  resolve(stats);
595
621
  }
@@ -600,7 +626,7 @@ function stats (callback) {
600
626
  return new Promise((resolve, reject) => {
601
627
  sharp.stats(this.options, (err, stats) => {
602
628
  if (err) {
603
- reject(err);
629
+ reject(is.nativeError(err, stack));
604
630
  } else {
605
631
  resolve(stats);
606
632
  }