sharp 0.33.5 → 0.35.3

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.
Files changed (49) hide show
  1. package/README.md +12 -18
  2. package/dist/channel.cjs +177 -0
  3. package/{lib/channel.js → dist/channel.mjs} +11 -8
  4. package/dist/colour.cjs +199 -0
  5. package/{lib/colour.js → dist/colour.mjs} +42 -23
  6. package/dist/composite.cjs +213 -0
  7. package/{lib/composite.js → dist/composite.mjs} +14 -11
  8. package/{lib/constructor.js → dist/constructor.cjs} +102 -43
  9. package/dist/constructor.mjs +511 -0
  10. package/dist/index.cjs +25 -0
  11. package/dist/index.d.cts +1999 -0
  12. package/dist/index.d.mts +2046 -0
  13. package/dist/index.mjs +25 -0
  14. package/dist/input.cjs +814 -0
  15. package/{lib/input.js → dist/input.mjs} +232 -76
  16. package/{lib/is.js → dist/is.cjs} +19 -45
  17. package/dist/is.mjs +143 -0
  18. package/{lib/libvips.js → dist/libvips.cjs} +52 -43
  19. package/dist/libvips.mjs +212 -0
  20. package/dist/operation.cjs +998 -0
  21. package/{lib/operation.js → dist/operation.mjs} +131 -91
  22. package/{lib/output.js → dist/output.cjs} +262 -61
  23. package/dist/output.mjs +1788 -0
  24. package/dist/resize.cjs +617 -0
  25. package/{lib/resize.js → dist/resize.mjs} +65 -35
  26. package/dist/sharp.cjs +174 -0
  27. package/dist/sharp.mjs +174 -0
  28. package/{lib/utility.js → dist/utility.cjs} +30 -25
  29. package/dist/utility.mjs +301 -0
  30. package/install/build.js +38 -0
  31. package/lib/index.d.ts +387 -142
  32. package/package.json +90 -85
  33. package/src/binding.gyp +49 -26
  34. package/src/common.cc +203 -111
  35. package/src/common.h +68 -40
  36. package/src/metadata.cc +106 -22
  37. package/src/metadata.h +15 -5
  38. package/src/operations.cc +62 -21
  39. package/src/operations.h +15 -3
  40. package/src/pipeline.cc +391 -201
  41. package/src/pipeline.h +36 -7
  42. package/src/sharp.cc +11 -8
  43. package/src/stats.cc +16 -13
  44. package/src/stats.h +6 -3
  45. package/src/utilities.cc +35 -15
  46. package/src/utilities.h +5 -2
  47. package/install/check.js +0 -41
  48. package/lib/index.js +0 -16
  49. package/lib/sharp.js +0 -114
@@ -1,9 +1,9 @@
1
- // Copyright 2013 Lovell Fuller and others.
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- 'use strict';
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
5
 
6
- const is = require('./is');
6
+ import is from './is.mjs';
7
7
 
8
8
  /**
9
9
  * Weighting to apply when using contain/cover fit.
@@ -72,7 +72,9 @@ const kernel = {
72
72
  cubic: 'cubic',
73
73
  mitchell: 'mitchell',
74
74
  lanczos2: 'lanczos2',
75
- lanczos3: 'lanczos3'
75
+ lanczos3: 'lanczos3',
76
+ mks2013: 'mks2013',
77
+ mks2021: 'mks2021'
76
78
  };
77
79
 
78
80
  /**
@@ -105,7 +107,7 @@ const mapFitToCanvas = {
105
107
  * @private
106
108
  */
107
109
  function isRotationExpected (options) {
108
- return (options.angle % 360) !== 0 || options.useExifOrientation === true || options.rotationAngle !== 0;
110
+ return (options.angle % 360) !== 0 || options.rotationAngle !== 0;
109
111
  }
110
112
 
111
113
  /**
@@ -127,7 +129,7 @@ function isResizeExpected (options) {
127
129
  *
128
130
  * Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
129
131
  *
130
- * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.svg">
132
+ * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="/api-resize-fit.svg">
131
133
  *
132
134
  * When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
133
135
  * - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
@@ -148,6 +150,8 @@ function isResizeExpected (options) {
148
150
  * - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
149
151
  * - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
150
152
  * - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
153
+ * - `mks2013`: Use a [Magic Kernel Sharp](https://johncostella.com/magic/mks.pdf) 2013 kernel, as adopted by Facebook.
154
+ * - `mks2021`: Use a Magic Kernel Sharp 2021 kernel, with more accurate (reduced) sharpening than the 2013 version.
151
155
  *
152
156
  * When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
153
157
  * Downsampling kernels without a matching upsampling interpolator map to `cubic`.
@@ -339,7 +343,7 @@ function resize (widthOrOptions, height, options) {
339
343
  }
340
344
  }
341
345
  if (isRotationExpected(this.options) && isResizeExpected(this.options)) {
342
- this.options.rotateBeforePreExtract = true;
346
+ this.options.rotateBefore = true;
343
347
  }
344
348
  return this;
345
349
  }
@@ -382,48 +386,52 @@ function resize (widthOrOptions, height, options) {
382
386
  * ...
383
387
  *
384
388
  * @param {(number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
385
- * @param {number} [extend.top=0]
386
- * @param {number} [extend.left=0]
387
- * @param {number} [extend.bottom=0]
388
- * @param {number} [extend.right=0]
389
+ * @param {number} [extend.top=0] - number of pixels to add to the top edge, valid values are integers in the range 0-10000
390
+ * @param {number} [extend.left=0] - number of pixels to add to the left edge, valid values are integers in the range 0-10000
391
+ * @param {number} [extend.bottom=0] - number of pixels to add to the bottom edge, valid values are integers in the range 0-10000
392
+ * @param {number} [extend.right=0] - number of pixels to add to the right edge, valid values are integers in the range 0-10000
389
393
  * @param {String} [extend.extendWith='background'] - populate new pixels using this method, one of: background, copy, repeat, mirror.
390
394
  * @param {String|Object} [extend.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
391
395
  * @returns {Sharp}
392
396
  * @throws {Error} Invalid parameters
393
397
  */
394
398
  function extend (extend) {
395
- if (is.integer(extend) && extend > 0) {
396
- this.options.extendTop = extend;
397
- this.options.extendBottom = extend;
398
- this.options.extendLeft = extend;
399
- this.options.extendRight = extend;
399
+ if (is.integer(extend)) {
400
+ if (is.inRange(extend, 1, 10000)) {
401
+ this.options.extendTop = extend;
402
+ this.options.extendBottom = extend;
403
+ this.options.extendLeft = extend;
404
+ this.options.extendRight = extend;
405
+ } else {
406
+ throw is.invalidParameterError('extend', 'integer between 1 and 10000', extend);
407
+ }
400
408
  } else if (is.object(extend)) {
401
409
  if (is.defined(extend.top)) {
402
- if (is.integer(extend.top) && extend.top >= 0) {
410
+ if (is.integer(extend.top) && is.inRange(extend.top, 0, 10000)) {
403
411
  this.options.extendTop = extend.top;
404
412
  } else {
405
- throw is.invalidParameterError('top', 'positive integer', extend.top);
413
+ throw is.invalidParameterError('top', 'integer between 0 and 10000', extend.top);
406
414
  }
407
415
  }
408
416
  if (is.defined(extend.bottom)) {
409
- if (is.integer(extend.bottom) && extend.bottom >= 0) {
417
+ if (is.integer(extend.bottom) && is.inRange(extend.bottom, 0, 10000)) {
410
418
  this.options.extendBottom = extend.bottom;
411
419
  } else {
412
- throw is.invalidParameterError('bottom', 'positive integer', extend.bottom);
420
+ throw is.invalidParameterError('bottom', 'integer between 0 and 10000', extend.bottom);
413
421
  }
414
422
  }
415
423
  if (is.defined(extend.left)) {
416
- if (is.integer(extend.left) && extend.left >= 0) {
424
+ if (is.integer(extend.left) && is.inRange(extend.left, 0, 10000)) {
417
425
  this.options.extendLeft = extend.left;
418
426
  } else {
419
- throw is.invalidParameterError('left', 'positive integer', extend.left);
427
+ throw is.invalidParameterError('left', 'integer between 0 and 10000', extend.left);
420
428
  }
421
429
  }
422
430
  if (is.defined(extend.right)) {
423
- if (is.integer(extend.right) && extend.right >= 0) {
431
+ if (is.integer(extend.right) && is.inRange(extend.right, 0, 10000)) {
424
432
  this.options.extendRight = extend.right;
425
433
  } else {
426
- throw is.invalidParameterError('right', 'positive integer', extend.right);
434
+ throw is.invalidParameterError('right', 'integer between 0 and 10000', extend.right);
427
435
  }
428
436
  }
429
437
  this._setBackgroundColourOption('extendBackground', extend.background);
@@ -463,10 +471,10 @@ function extend (extend) {
463
471
  * });
464
472
  *
465
473
  * @param {Object} options - describes the region to extract using integral pixel values
466
- * @param {number} options.left - zero-indexed offset from left edge
467
- * @param {number} options.top - zero-indexed offset from top edge
468
- * @param {number} options.width - width of region to extract
469
- * @param {number} options.height - height of region to extract
474
+ * @param {number} options.left - zero-indexed offset from left edge, an integer between 0 and 100000000
475
+ * @param {number} options.top - zero-indexed offset from top edge, an integer between 0 and 100000000
476
+ * @param {number} options.width - width of region to extract, an integer between 0 and 100000000
477
+ * @param {number} options.height - height of region to extract, an integer between 0 and 100000000
470
478
  * @returns {Sharp}
471
479
  * @throws {Error} Invalid parameters
472
480
  */
@@ -477,18 +485,21 @@ function extract (options) {
477
485
  }
478
486
  ['left', 'top', 'width', 'height'].forEach(function (name) {
479
487
  const value = options[name];
480
- if (is.integer(value) && value >= 0) {
488
+ if (is.integer(value) && is.inRange(value, 0, 100000000)) {
481
489
  this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
482
490
  } else {
483
- throw is.invalidParameterError(name, 'integer', value);
491
+ throw is.invalidParameterError(name, 'integer between 0 and 100000000', value);
484
492
  }
485
493
  }, this);
486
494
  // Ensure existing rotation occurs before pre-resize extraction
487
495
  if (isRotationExpected(this.options) && !isResizeExpected(this.options)) {
488
496
  if (this.options.widthPre === -1 || this.options.widthPost === -1) {
489
- this.options.rotateBeforePreExtract = true;
497
+ this.options.rotateBefore = true;
490
498
  }
491
499
  }
500
+ if (this.options.input.autoOrient) {
501
+ this.options.orientBefore = true;
502
+ }
492
503
  return this;
493
504
  }
494
505
 
@@ -499,6 +510,8 @@ function extract (options) {
499
510
  *
500
511
  * If the result of this operation would trim an image to nothing then no change is made.
501
512
  *
513
+ * Use the `lineArt` and `threshold` options for control over sensitivity.
514
+ *
502
515
  * The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
503
516
  *
504
517
  * @example
@@ -533,10 +546,19 @@ function extract (options) {
533
546
  * })
534
547
  * .toBuffer();
535
548
  *
549
+ * @example
550
+ * // Trim image leaving (up to) a 10 pixel margin around the trimmed content.
551
+ * const output = await sharp(input)
552
+ * .trim({
553
+ * margin: 10
554
+ * })
555
+ * .toBuffer();
556
+ *
536
557
  * @param {Object} [options]
537
558
  * @param {string|Object} [options.background='top-left pixel'] - Background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel.
538
559
  * @param {number} [options.threshold=10] - Allowed difference from the above colour, a positive number.
539
560
  * @param {boolean} [options.lineArt=false] - Does the input more closely resemble line art (e.g. vector) rather than being photographic?
561
+ * @param {number} [options.margin=0] - Leave a margin around trimmed content, integral number of pixels between 0 and 10000000.
540
562
  * @returns {Sharp}
541
563
  * @throws {Error} Invalid parameters
542
564
  */
@@ -557,21 +579,29 @@ function trim (options) {
557
579
  if (is.defined(options.lineArt)) {
558
580
  this._setBooleanOption('trimLineArt', options.lineArt);
559
581
  }
582
+ if (is.defined(options.margin)) {
583
+ if (is.integer(options.margin) && is.inRange(options.margin, 0, 10000000)) {
584
+ this.options.trimMargin = options.margin;
585
+ } else {
586
+ throw is.invalidParameterError('margin', 'integer between 0 and 10000000', options.margin);
587
+ }
588
+ }
560
589
  } else {
561
590
  throw is.invalidParameterError('trim', 'object', options);
562
591
  }
563
592
  }
564
593
  if (isRotationExpected(this.options)) {
565
- this.options.rotateBeforePreExtract = true;
594
+ this.options.rotateBefore = true;
566
595
  }
567
596
  return this;
568
597
  }
569
598
 
570
599
  /**
571
600
  * Decorate the Sharp prototype with resize-related functions.
601
+ * @module Sharp
572
602
  * @private
573
603
  */
574
- module.exports = function (Sharp) {
604
+ export default (Sharp) => {
575
605
  Object.assign(Sharp.prototype, {
576
606
  resize,
577
607
  extend,
package/dist/sharp.cjs ADDED
@@ -0,0 +1,174 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // Inspects the runtime environment and exports the relevant sharp.node binary
7
+
8
+
9
+ const { familySync, versionSync } = require("detect-libc");
10
+
11
+ const libvips = require("./libvips.cjs");
12
+ const pkg = require('../package.json');
13
+
14
+
15
+ const { version } = pkg;
16
+
17
+ const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = libvips;
18
+ const runtimePlatform = runtimePlatformArch();
19
+
20
+ /* node:coverage disable */
21
+
22
+ let sharp;
23
+ const errors = [];
24
+ try {
25
+ sharp = require(`../src/build/Release/sharp-${runtimePlatform}-${version}.node`);
26
+ } catch (err) {
27
+ errors.push(err);
28
+ }
29
+ if (!sharp) {
30
+ try {
31
+ sharp = require(`../src/build/Release/sharp-wasm32-${version}.node`);
32
+ } catch (err) {
33
+ errors.push(err);
34
+ }
35
+ }
36
+ if (!sharp) {
37
+ try {
38
+ switch (runtimePlatform) {
39
+ case "darwin-arm64":
40
+ sharp = require("@img/sharp-darwin-arm64/sharp.node");
41
+ break;
42
+ case "darwin-x64":
43
+ sharp = require("@img/sharp-darwin-x64/sharp.node");
44
+ break;
45
+ case "linux-arm":
46
+ sharp = require("@img/sharp-linux-arm/sharp.node");
47
+ break;
48
+ case "linux-arm64":
49
+ sharp = require("@img/sharp-linux-arm64/sharp.node");
50
+ break;
51
+ case "linux-ppc64":
52
+ sharp = require("@img/sharp-linux-ppc64/sharp.node");
53
+ break;
54
+ case "linux-riscv64":
55
+ sharp = require("@img/sharp-linux-riscv64/sharp.node");
56
+ break;
57
+ case "linux-s390x":
58
+ sharp = require("@img/sharp-linux-s390x/sharp.node");
59
+ break;
60
+ case "linux-x64":
61
+ sharp = require("@img/sharp-linux-x64/sharp.node");
62
+ break;
63
+ case "linuxmusl-arm64":
64
+ sharp = require("@img/sharp-linuxmusl-arm64/sharp.node");
65
+ break;
66
+ case "linuxmusl-x64":
67
+ sharp = require("@img/sharp-linuxmusl-x64/sharp.node");
68
+ break;
69
+ case "win32-arm64":
70
+ sharp = require("@img/sharp-win32-arm64/sharp.node");
71
+ break;
72
+ case "win32-ia32":
73
+ sharp = require("@img/sharp-win32-ia32/sharp.node");
74
+ break;
75
+ case "win32-x64":
76
+ sharp = require("@img/sharp-win32-x64/sharp.node");
77
+ break;
78
+ case "freebsd-arm64":
79
+ case "freebsd-x64":
80
+ sharp = require("@img/sharp-freebsd-wasm32/sharp.node");
81
+ break;
82
+ case "linux-wasm32":
83
+ sharp = require("@img/sharp-webcontainers-wasm32/sharp.node");
84
+ break;
85
+ }
86
+ if (sharp && ["linux-x64", "linuxmusl-x64"].includes(runtimePlatform) && !sharp._isUsingX64V2()) {
87
+ const err = new Error("Prebuilt binaries for Linux x64 require v2 microarchitecture");
88
+ err.code = "Unsupported CPU";
89
+ errors.push(err);
90
+ sharp = null;
91
+ }
92
+ if (sharp && process.versions.electron && runtimePlatform.startsWith("linux")) {
93
+ process.emitWarning(
94
+ "Binaries provided by Electron for use on Linux may be incompatible with sharp - see https://sharp.pixelplumbing.com/install#electron-and-linux",
95
+ { code: "SharpElectronLinux" }
96
+ );
97
+ }
98
+ } catch (err) {
99
+ errors.push(err);
100
+ }
101
+ }
102
+ if (!sharp) {
103
+ try {
104
+ sharp = require("@img/sharp-wasm32/sharp.node");
105
+ } catch (err) {
106
+ errors.push(err);
107
+ }
108
+ }
109
+
110
+ if (!sharp) {
111
+ const [isLinux, isMacOs, isWindows] = ["linux", "darwin", "win32"].map((os) => runtimePlatform.startsWith(os));
112
+
113
+ const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`];
114
+ errors.forEach((err) => {
115
+ if (!err.code.endsWith("MODULE_NOT_FOUND")) {
116
+ help.push(`${err.code}: ${err.message}`);
117
+ }
118
+ });
119
+ const messages = errors.map((err) => err.message).join(" ");
120
+ help.push("Possible solutions:");
121
+ // Common error messages
122
+ if (isUnsupportedNodeRuntime()) {
123
+ const { found, expected } = isUnsupportedNodeRuntime();
124
+ help.push("- Please upgrade Node.js:", ` Found ${found}`, ` Requires ${expected}`);
125
+ } else if (prebuiltPlatforms.includes(runtimePlatform)) {
126
+ const [os, cpu] = runtimePlatform.split("-");
127
+ const libc = os.endsWith("musl") ? " --libc=musl" : "";
128
+ help.push(
129
+ "- Ensure optional dependencies can be installed:",
130
+ " npm install --include=optional sharp",
131
+ "- Ensure your package manager supports multi-platform installation:",
132
+ " See https://sharp.pixelplumbing.com/install#cross-platform",
133
+ "- Add platform-specific dependencies:",
134
+ ` npm install --os=${os.replace("musl", "")}${libc} --cpu=${cpu} sharp`,
135
+ );
136
+ } else {
137
+ help.push(
138
+ `- Manually install libvips >= ${minimumLibvipsVersion}`,
139
+ " See https://sharp.pixelplumbing.com/install#building-from-source",
140
+ "- Add WebAssembly-based dependencies:",
141
+ " npm install sharp @img/sharp-wasm32",
142
+ );
143
+ }
144
+ if (isLinux && /(symbol not found|CXXABI_)/i.test(messages)) {
145
+ try {
146
+ const { config } = require(`@img/sharp-libvips-${runtimePlatform}/package`);
147
+ const libcFound = `${familySync()} ${versionSync()}`;
148
+ const libcRequires = `${config.musl ? "musl" : "glibc"} ${config.musl || config.glibc}`;
149
+ help.push("- Update your OS:", ` Found ${libcFound}`, ` Requires ${libcRequires}`);
150
+ } catch (_errEngines) {}
151
+ }
152
+ if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
153
+ help.push("- Remove the Node.js Snap, which does not support native modules", " snap remove node");
154
+ }
155
+ if (isMacOs && /Incompatible library version/.test(messages)) {
156
+ help.push("- Update Homebrew:", " brew update && brew upgrade vips");
157
+ }
158
+ if (errors.some((err) => err.code === "ERR_DLOPEN_DISABLED")) {
159
+ help.push("- Run Node.js without using the --no-addons flag");
160
+ }
161
+ // Link to installation docs
162
+ if (isWindows && /The specified procedure could not be found/.test(messages)) {
163
+ help.push(
164
+ "- Using the canvas package on Windows?",
165
+ " See https://sharp.pixelplumbing.com/install#canvas-and-windows",
166
+ "- Check for outdated versions of sharp in the dependency tree:",
167
+ " npm ls sharp",
168
+ );
169
+ }
170
+ help.push("- Consult the installation documentation:", " See https://sharp.pixelplumbing.com/install");
171
+ throw new Error(help.join("\n"));
172
+ }
173
+
174
+ module.exports = sharp;
package/dist/sharp.mjs ADDED
@@ -0,0 +1,174 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // Inspects the runtime environment and exports the relevant sharp.node binary
7
+
8
+ import { createRequire } from "node:module"
9
+ import { familySync, versionSync } from "detect-libc";
10
+
11
+ import libvips from "./libvips.mjs";
12
+ import pkg from '../package.json' with { type: 'json' };
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const { version } = pkg;
16
+
17
+ const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = libvips;
18
+ const runtimePlatform = runtimePlatformArch();
19
+
20
+ /* node:coverage disable */
21
+
22
+ let sharp;
23
+ const errors = [];
24
+ try {
25
+ sharp = require(`../src/build/Release/sharp-${runtimePlatform}-${version}.node`);
26
+ } catch (err) {
27
+ errors.push(err);
28
+ }
29
+ if (!sharp) {
30
+ try {
31
+ sharp = require(`../src/build/Release/sharp-wasm32-${version}.node`);
32
+ } catch (err) {
33
+ errors.push(err);
34
+ }
35
+ }
36
+ if (!sharp) {
37
+ try {
38
+ switch (runtimePlatform) {
39
+ case "darwin-arm64":
40
+ sharp = require("@img/sharp-darwin-arm64/sharp.node");
41
+ break;
42
+ case "darwin-x64":
43
+ sharp = require("@img/sharp-darwin-x64/sharp.node");
44
+ break;
45
+ case "linux-arm":
46
+ sharp = require("@img/sharp-linux-arm/sharp.node");
47
+ break;
48
+ case "linux-arm64":
49
+ sharp = require("@img/sharp-linux-arm64/sharp.node");
50
+ break;
51
+ case "linux-ppc64":
52
+ sharp = require("@img/sharp-linux-ppc64/sharp.node");
53
+ break;
54
+ case "linux-riscv64":
55
+ sharp = require("@img/sharp-linux-riscv64/sharp.node");
56
+ break;
57
+ case "linux-s390x":
58
+ sharp = require("@img/sharp-linux-s390x/sharp.node");
59
+ break;
60
+ case "linux-x64":
61
+ sharp = require("@img/sharp-linux-x64/sharp.node");
62
+ break;
63
+ case "linuxmusl-arm64":
64
+ sharp = require("@img/sharp-linuxmusl-arm64/sharp.node");
65
+ break;
66
+ case "linuxmusl-x64":
67
+ sharp = require("@img/sharp-linuxmusl-x64/sharp.node");
68
+ break;
69
+ case "win32-arm64":
70
+ sharp = require("@img/sharp-win32-arm64/sharp.node");
71
+ break;
72
+ case "win32-ia32":
73
+ sharp = require("@img/sharp-win32-ia32/sharp.node");
74
+ break;
75
+ case "win32-x64":
76
+ sharp = require("@img/sharp-win32-x64/sharp.node");
77
+ break;
78
+ case "freebsd-arm64":
79
+ case "freebsd-x64":
80
+ sharp = require("@img/sharp-freebsd-wasm32/sharp.node");
81
+ break;
82
+ case "linux-wasm32":
83
+ sharp = require("@img/sharp-webcontainers-wasm32/sharp.node");
84
+ break;
85
+ }
86
+ if (sharp && ["linux-x64", "linuxmusl-x64"].includes(runtimePlatform) && !sharp._isUsingX64V2()) {
87
+ const err = new Error("Prebuilt binaries for Linux x64 require v2 microarchitecture");
88
+ err.code = "Unsupported CPU";
89
+ errors.push(err);
90
+ sharp = null;
91
+ }
92
+ if (sharp && process.versions.electron && runtimePlatform.startsWith("linux")) {
93
+ process.emitWarning(
94
+ "Binaries provided by Electron for use on Linux may be incompatible with sharp - see https://sharp.pixelplumbing.com/install#electron-and-linux",
95
+ { code: "SharpElectronLinux" }
96
+ );
97
+ }
98
+ } catch (err) {
99
+ errors.push(err);
100
+ }
101
+ }
102
+ if (!sharp) {
103
+ try {
104
+ sharp = require("@img/sharp-wasm32/sharp.node");
105
+ } catch (err) {
106
+ errors.push(err);
107
+ }
108
+ }
109
+
110
+ if (!sharp) {
111
+ const [isLinux, isMacOs, isWindows] = ["linux", "darwin", "win32"].map((os) => runtimePlatform.startsWith(os));
112
+
113
+ const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`];
114
+ errors.forEach((err) => {
115
+ if (!err.code.endsWith("MODULE_NOT_FOUND")) {
116
+ help.push(`${err.code}: ${err.message}`);
117
+ }
118
+ });
119
+ const messages = errors.map((err) => err.message).join(" ");
120
+ help.push("Possible solutions:");
121
+ // Common error messages
122
+ if (isUnsupportedNodeRuntime()) {
123
+ const { found, expected } = isUnsupportedNodeRuntime();
124
+ help.push("- Please upgrade Node.js:", ` Found ${found}`, ` Requires ${expected}`);
125
+ } else if (prebuiltPlatforms.includes(runtimePlatform)) {
126
+ const [os, cpu] = runtimePlatform.split("-");
127
+ const libc = os.endsWith("musl") ? " --libc=musl" : "";
128
+ help.push(
129
+ "- Ensure optional dependencies can be installed:",
130
+ " npm install --include=optional sharp",
131
+ "- Ensure your package manager supports multi-platform installation:",
132
+ " See https://sharp.pixelplumbing.com/install#cross-platform",
133
+ "- Add platform-specific dependencies:",
134
+ ` npm install --os=${os.replace("musl", "")}${libc} --cpu=${cpu} sharp`,
135
+ );
136
+ } else {
137
+ help.push(
138
+ `- Manually install libvips >= ${minimumLibvipsVersion}`,
139
+ " See https://sharp.pixelplumbing.com/install#building-from-source",
140
+ "- Add WebAssembly-based dependencies:",
141
+ " npm install sharp @img/sharp-wasm32",
142
+ );
143
+ }
144
+ if (isLinux && /(symbol not found|CXXABI_)/i.test(messages)) {
145
+ try {
146
+ const { config } = require(`@img/sharp-libvips-${runtimePlatform}/package`);
147
+ const libcFound = `${familySync()} ${versionSync()}`;
148
+ const libcRequires = `${config.musl ? "musl" : "glibc"} ${config.musl || config.glibc}`;
149
+ help.push("- Update your OS:", ` Found ${libcFound}`, ` Requires ${libcRequires}`);
150
+ } catch (_errEngines) {}
151
+ }
152
+ if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
153
+ help.push("- Remove the Node.js Snap, which does not support native modules", " snap remove node");
154
+ }
155
+ if (isMacOs && /Incompatible library version/.test(messages)) {
156
+ help.push("- Update Homebrew:", " brew update && brew upgrade vips");
157
+ }
158
+ if (errors.some((err) => err.code === "ERR_DLOPEN_DISABLED")) {
159
+ help.push("- Run Node.js without using the --no-addons flag");
160
+ }
161
+ // Link to installation docs
162
+ if (isWindows && /The specified procedure could not be found/.test(messages)) {
163
+ help.push(
164
+ "- Using the canvas package on Windows?",
165
+ " See https://sharp.pixelplumbing.com/install#canvas-and-windows",
166
+ "- Check for outdated versions of sharp in the dependency tree:",
167
+ " npm ls sharp",
168
+ );
169
+ }
170
+ help.push("- Consult the installation documentation:", " See https://sharp.pixelplumbing.com/install");
171
+ throw new Error(help.join("\n"));
172
+ }
173
+
174
+ export default sharp;