@depup/sharp-cli 5.3.0-depup.0 → 6.0.0-depup.0

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 (48) hide show
  1. package/.github/workflows/ci.yml +30 -0
  2. package/CHANGELOG.md +20 -0
  3. package/README.md +6 -9
  4. package/bin/cli.js +5 -5
  5. package/changes.json +4 -16
  6. package/cmd/channel-manipulation/bandbool.js +6 -7
  7. package/cmd/channel-manipulation/ensure-alpha.js +5 -8
  8. package/cmd/channel-manipulation/extract-channel.js +3 -7
  9. package/cmd/channel-manipulation/join-channel.js +5 -8
  10. package/cmd/channel-manipulation/remove-alpha.js +2 -8
  11. package/cmd/colour-manipulation/greyscale.js +2 -8
  12. package/cmd/colour-manipulation/pipeline-colourspace.js +4 -8
  13. package/cmd/colour-manipulation/tint.js +3 -8
  14. package/cmd/colour-manipulation/tocolourspace.js +3 -7
  15. package/cmd/compositing/composite.js +10 -7
  16. package/cmd/operations/affine.js +9 -11
  17. package/cmd/operations/blur.js +3 -8
  18. package/cmd/operations/boolean.js +3 -7
  19. package/cmd/operations/clahe.js +4 -9
  20. package/cmd/operations/convolve.js +5 -9
  21. package/cmd/operations/dilate.js +2 -8
  22. package/cmd/operations/erode.js +2 -8
  23. package/cmd/operations/flatten.js +2 -8
  24. package/cmd/operations/flip.js +3 -8
  25. package/cmd/operations/flop.js +3 -8
  26. package/cmd/operations/gamma.js +2 -8
  27. package/cmd/operations/linear.js +2 -8
  28. package/cmd/operations/median.js +2 -8
  29. package/cmd/operations/modulate.js +10 -9
  30. package/cmd/operations/negate.js +2 -8
  31. package/cmd/operations/normalise.js +5 -9
  32. package/cmd/operations/recomb.js +2 -8
  33. package/cmd/operations/rotate.js +2 -8
  34. package/cmd/operations/sharpen.js +8 -9
  35. package/cmd/operations/threshold.js +2 -8
  36. package/cmd/operations/unflatten.js +2 -8
  37. package/cmd/output.js +7 -10
  38. package/cmd/resizing/extend.js +4 -10
  39. package/cmd/resizing/extract.js +3 -9
  40. package/cmd/resizing/resize.js +4 -10
  41. package/cmd/resizing/trim.js +12 -8
  42. package/{lib/queue.js → eslint.config.mjs} +20 -17
  43. package/lib/cli.js +473 -333
  44. package/lib/constants.js +4 -6
  45. package/lib/convert.js +93 -55
  46. package/lib/index.js +46 -17
  47. package/lib/utils.js +50 -0
  48. package/package.json +24 -33
package/lib/cli.js CHANGED
@@ -21,18 +21,52 @@
21
21
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- // Strict mode.
25
- "use strict";
26
-
27
24
  // Package modules.
28
- const pick = require("lodash.pick");
29
- const sharp = require("sharp");
30
- const yargs = require("yargs");
25
+ import sharp from "sharp";
26
+ import yargs from "yargs";
31
27
 
32
28
  // Local modules.
33
- const constants = require("./constants");
34
- const pkg = require("../package.json");
35
- const queue = require("./queue");
29
+ import affine from "../cmd/operations/affine.js";
30
+ import bandbool from "../cmd/channel-manipulation/bandbool.js";
31
+ import blur from "../cmd/operations/blur.js";
32
+ import boolean from "../cmd/operations/boolean.js";
33
+ import clahe from "../cmd/operations/clahe.js";
34
+ import composite from "../cmd/compositing/composite.js";
35
+ import convolve from "../cmd/operations/convolve.js";
36
+ import dilate from "../cmd/operations/dilate.js";
37
+ import ensureAlpha from "../cmd/channel-manipulation/ensure-alpha.js";
38
+ import erode from "../cmd/operations/erode.js";
39
+ import extend from "../cmd/resizing/extend.js";
40
+ import extract from "../cmd/resizing/extract.js";
41
+ import extractChannel from "../cmd/channel-manipulation/extract-channel.js";
42
+ import flatten from "../cmd/operations/flatten.js";
43
+ import flip from "../cmd/operations/flip.js";
44
+ import flop from "../cmd/operations/flop.js";
45
+ import gamma from "../cmd/operations/gamma.js";
46
+ import greyscale from "../cmd/colour-manipulation/greyscale.js";
47
+ import joinChannel from "../cmd/channel-manipulation/join-channel.js";
48
+ import linear from "../cmd/operations/linear.js";
49
+ import median from "../cmd/operations/median.js";
50
+ import modulate from "../cmd/operations/modulate.js";
51
+ import negate from "../cmd/operations/negate.js";
52
+ import normalise from "../cmd/operations/normalise.js";
53
+ import pipelineColourspace from "../cmd/colour-manipulation/pipeline-colourspace.js";
54
+ import recomb from "../cmd/operations/recomb.js";
55
+ import removeAlpha from "../cmd/channel-manipulation/remove-alpha.js";
56
+ import resize from "../cmd/resizing/resize.js";
57
+ import rotate from "../cmd/operations/rotate.js";
58
+ import sharpen from "../cmd/operations/sharpen.js";
59
+ import threshold from "../cmd/operations/threshold.js";
60
+ import tint from "../cmd/colour-manipulation/tint.js";
61
+ import tile from "../cmd/output.js";
62
+ import toColourspace from "../cmd/colour-manipulation/tocolourspace.js";
63
+ import trim from "../cmd/resizing/trim.js";
64
+ import unflatten from "../cmd/operations/unflatten.js";
65
+ import constants from "./constants.js";
66
+ import { pick } from "./utils.js";
67
+
68
+ // Assets.
69
+ import pkg from "../package.json" with { type: "json" };
36
70
 
37
71
  // Configure.
38
72
  const IS_TEXT_TERMINAL = process.stdin.isTTY;
@@ -44,6 +78,20 @@ const optimize = "Optimization Options";
44
78
  const output = "Output Options";
45
79
 
46
80
  const globalOptions = {
81
+ dry: {
82
+ alias: "n",
83
+ desc: "Process images without writing output files",
84
+ group: global,
85
+ type: "boolean",
86
+ },
87
+
88
+ print: {
89
+ desc: "Print input and output metadata as JSON",
90
+ group: global,
91
+ implies: IS_TEXT_TERMINAL ? undefined : "dry",
92
+ type: "boolean",
93
+ },
94
+
47
95
  // @see https://sharp.pixelplumbing.com/api-constructor/
48
96
  input: {
49
97
  alias: "i",
@@ -52,6 +100,7 @@ const globalOptions = {
52
100
  desc: "Path to (an) image file(s)",
53
101
  group: global,
54
102
  implies: "output",
103
+ requiresArg: true,
55
104
  type: "array",
56
105
  },
57
106
 
@@ -62,6 +111,7 @@ const globalOptions = {
62
111
  demand: IS_TEXT_TERMINAL,
63
112
  desc: "Directory or URI template to write the image files to",
64
113
  group: global,
114
+ nargs: 1,
65
115
  type: "string",
66
116
  },
67
117
 
@@ -69,12 +119,13 @@ const globalOptions = {
69
119
  timeout: {
70
120
  desc: "Number of seconds after which processing will be stopped",
71
121
  group: global,
122
+ nargs: 1,
72
123
  type: "number",
73
124
  },
74
125
  };
75
126
 
76
127
  // @see https://sharp.pixelplumbing.com/api-constructor
77
- const inputOptions = {
128
+ export const inputOptions = {
78
129
  animated: {
79
130
  desc: "Read all frames/pages of an animated image",
80
131
  group: input,
@@ -85,18 +136,19 @@ const inputOptions = {
85
136
  group: input,
86
137
  type: "boolean",
87
138
  },
88
- failOn: {
89
- choices: constants.FAIL_ON,
90
- defaultDescription: "warning",
91
- desc: "Level of sensitivity to invalid images",
92
- group: input,
93
- },
94
139
  density: {
95
140
  desc: "DPI for vector images",
96
141
  defaultDescription: 72,
97
142
  group: input,
143
+ nargs: 1,
98
144
  type: "number",
99
145
  },
146
+ failOn: {
147
+ choices: constants.FAIL_ON,
148
+ defaultDescription: "warning",
149
+ desc: "Level of sensitivity to invalid images",
150
+ group: input,
151
+ },
100
152
  ignoreIcc: {
101
153
  default: false,
102
154
  desc: "Should the embedded ICC profile, if any, be ignored",
@@ -107,24 +159,35 @@ const inputOptions = {
107
159
  desc: "Level to extract from a multi-level input (OpenSlide), zero based",
108
160
  defaultDescription: 0,
109
161
  group: input,
162
+ nargs: 1,
110
163
  type: "number",
111
164
  },
112
165
  limitInputPixels: {
113
166
  defaultDescription: 0x3fff * 0x3fff,
114
167
  desc: "Do not process input images where the number of pixels (width x height) exceeds this limit",
115
168
  group: input,
169
+ nargs: 1,
170
+ type: "number",
171
+ },
172
+ limitInputChannels: {
173
+ defaultDescription: 5,
174
+ desc: "Do not process input images where the number of channels exceeds this limit",
175
+ group: input,
176
+ nargs: 1,
116
177
  type: "number",
117
178
  },
118
179
  page: {
119
180
  defaultDescription: 0,
120
181
  desc: "Page number to start extracting from for multi-page input",
121
182
  group: input,
183
+ nargs: 1,
122
184
  type: "number",
123
185
  },
124
186
  pages: {
125
187
  defaultDescription: 1,
126
188
  desc: "Number of pages to extract for multi-page input",
127
189
  group: input,
190
+ nargs: 1,
128
191
  type: "number",
129
192
  },
130
193
  pdfBackground: {
@@ -142,6 +205,7 @@ const inputOptions = {
142
205
  defaultDescription: -1,
143
206
  desc: "subIFD to extract for OME-TIFF",
144
207
  group: input,
208
+ nargs: 1,
145
209
  type: "number",
146
210
  },
147
211
  unlimited: {
@@ -165,6 +229,7 @@ const outputOptions = {
165
229
  desc: "zlib compression level",
166
230
  defaultDescription: 6,
167
231
  group: output,
232
+ nargs: 1,
168
233
  type: "number",
169
234
  },
170
235
 
@@ -184,6 +249,14 @@ const outputOptions = {
184
249
  type: "boolean",
185
250
  },
186
251
 
252
+ // @see https://sharp.pixelplumbing.com/api-output#keepgainmap
253
+ keepGainMap: {
254
+ conflicts: "withGainMap",
255
+ desc: "Attempt to process the image and gain map separately, recombining them into a single output image",
256
+ group: output,
257
+ type: "boolean",
258
+ },
259
+
187
260
  // @see https://sharp.pixelplumbing.com/api-output#withmetadata
188
261
  metadata: {
189
262
  alias: ["m", "withMetadata"],
@@ -194,6 +267,7 @@ const outputOptions = {
194
267
  "metadata.density": {
195
268
  desc: "Number of pixels per inch (DPI)",
196
269
  group: output,
270
+ nargs: 1,
197
271
  type: "number",
198
272
  },
199
273
  "metadata.exif": {
@@ -211,9 +285,26 @@ const outputOptions = {
211
285
  "metadata.orientation": {
212
286
  desc: "Used to update the EXIF Orientation tag",
213
287
  group: output,
288
+ nargs: 1,
214
289
  type: "number",
215
290
  },
216
291
 
292
+ // @see https://sharp.pixelplumbing.com/api-output#withdensity
293
+ withDensity: {
294
+ desc: "Set output density (DPI) in EXIF metadata",
295
+ group: output,
296
+ nargs: 1,
297
+ type: "number",
298
+ },
299
+
300
+ // @see https://sharp.pixelplumbing.com/api-output#withgainmap
301
+ withGainMap: {
302
+ conflicts: "keepGainMap",
303
+ desc: "Convert the main image to HDR (High Dynamic Range) before further processing",
304
+ group: output,
305
+ type: "boolean",
306
+ },
307
+
217
308
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
218
309
  // @see https://sharp.pixelplumbing.com/api-output#png
219
310
  progressive: {
@@ -232,6 +323,7 @@ const outputOptions = {
232
323
  desc: "Quality",
233
324
  defaultDescription: "80",
234
325
  group: output,
326
+ nargs: 1,
235
327
  type: "number",
236
328
  },
237
329
  };
@@ -249,6 +341,7 @@ const optimizationOptions = {
249
341
  desc: "Quality of alpha layer",
250
342
  defaultDescription: "80",
251
343
  group: optimize,
344
+ nargs: 1,
252
345
  type: "number",
253
346
  },
254
347
 
@@ -258,6 +351,7 @@ const optimizationOptions = {
258
351
  defaultDescription: 8,
259
352
  desc: "Reduce bitdepth to 1, 2, or 4 bit",
260
353
  group: optimize,
354
+ nargs: 1,
261
355
  },
262
356
 
263
357
  // @see https://sharp.pixelplumbing.com/api-output#avif
@@ -276,6 +370,7 @@ const optimizationOptions = {
276
370
  defaultDescription: 256,
277
371
  desc: "Maximum number of palette entries",
278
372
  group: optimize,
373
+ nargs: 1,
279
374
  type: "number",
280
375
  },
281
376
 
@@ -291,6 +386,7 @@ const optimizationOptions = {
291
386
  delay: {
292
387
  desc: "Delay(s) between animation frames",
293
388
  group: optimize,
389
+ nargs: 1,
294
390
  type: "number",
295
391
  },
296
392
 
@@ -300,6 +396,7 @@ const optimizationOptions = {
300
396
  desc: "Level of Floyd-Steinberg error diffusion",
301
397
  defaultDescription: "1.0",
302
398
  group: optimize,
399
+ nargs: 1,
303
400
  type: "number",
304
401
  },
305
402
 
@@ -312,15 +409,24 @@ const optimizationOptions = {
312
409
  defaultDescription: "7 (GIF, PNG) / 4",
313
410
  desc: "Level of CPU effort to reduce file size",
314
411
  group: optimize,
412
+ nargs: 1,
315
413
  type: "number",
316
414
  },
317
415
 
416
+ // @see https://sharp.pixelplumbing.com/api-output#webp
417
+ exact: {
418
+ desc: "Preserve the colour data in transparent pixels",
419
+ group: optimize,
420
+ type: "boolean",
421
+ },
422
+
318
423
  // @see https://sharp.pixelplumbing.com/api-output#heif
319
424
  hbitdepth: {
320
425
  choices: [8, 10, 12],
321
426
  defaultDescription: 8,
322
427
  desc: "Set bitdepth to 8, 10, or 12 bit",
323
428
  group: optimize,
429
+ nargs: 1,
324
430
  },
325
431
 
326
432
  // @see https://sharp.pixelplumbing.com/api-output#heif
@@ -335,6 +441,7 @@ const optimizationOptions = {
335
441
  interFrameMaxError: {
336
442
  desc: "Maximum inter-frame error for transparency",
337
443
  group: optimize,
444
+ nargs: 1,
338
445
  type: "number",
339
446
  },
340
447
 
@@ -342,6 +449,7 @@ const optimizationOptions = {
342
449
  interPaletteMaxError: {
343
450
  desc: "Maximum inter-palette error for palette reuse",
344
451
  group: optimize,
452
+ nargs: 1,
345
453
  type: "number",
346
454
  },
347
455
 
@@ -350,6 +458,7 @@ const optimizationOptions = {
350
458
  default: 0,
351
459
  desc: "Number of animation iterations",
352
460
  group: optimize,
461
+ nargs: 1,
353
462
  type: "number",
354
463
  },
355
464
 
@@ -465,6 +574,7 @@ const optimizationOptions = {
465
574
  defaultDescription: "0",
466
575
  desc: "Quantization table to use",
467
576
  group: optimize,
577
+ nargs: 1,
468
578
  type: "number",
469
579
  },
470
580
 
@@ -510,6 +620,7 @@ const optimizationOptions = {
510
620
  tileHeight: {
511
621
  desc: "Vertical tile size",
512
622
  group: optimize,
623
+ nargs: 1,
513
624
  type: "number",
514
625
  },
515
626
 
@@ -517,6 +628,7 @@ const optimizationOptions = {
517
628
  tileWidth: {
518
629
  desc: "Horizontal tile size",
519
630
  group: optimize,
631
+ nargs: 1,
520
632
  type: "number",
521
633
  },
522
634
 
@@ -527,11 +639,21 @@ const optimizationOptions = {
527
639
  type: "boolean",
528
640
  },
529
641
 
642
+ // @see https://sharp.pixelplumbing.com/api-output#avif
643
+ // @see https://sharp.pixelplumbing.com/api-output#heif
644
+ tune: {
645
+ choices: constants.TUNE,
646
+ defaultDescription: "auto",
647
+ desc: "Tune output for a quality metric",
648
+ group: optimize,
649
+ },
650
+
530
651
  // @see https://sharp.pixelplumbing.com/api-output#tiff
531
652
  xres: {
532
653
  defaultDescription: "1.0",
533
654
  desc: "Horizontal resolution",
534
655
  group: optimize,
656
+ nargs: 1,
535
657
  type: "number",
536
658
  },
537
659
 
@@ -540,6 +662,7 @@ const optimizationOptions = {
540
662
  defaultDescription: "1.0",
541
663
  desc: "Vertical resolution",
542
664
  group: optimize,
665
+ nargs: 1,
543
666
  type: "number",
544
667
  },
545
668
  };
@@ -551,8 +674,13 @@ const options = {
551
674
  ...optimizationOptions,
552
675
  };
553
676
 
677
+ // Helpers.
678
+ function createContext() {
679
+ return { "#queue": [] };
680
+ }
681
+
554
682
  // Configure.
555
- const cli = yargs
683
+ const cli = yargs()
556
684
  .parserConfiguration({ "populate--": true })
557
685
  .strict()
558
686
  .usage("$0 <options> [command..]")
@@ -591,324 +719,336 @@ const cli = yargs
591
719
  .group(["help", "version"], "Misc. Options")
592
720
 
593
721
  // Commands.
594
- // Avoid `yargs.commandDir()` as it uses insertion order, not alphabetical.
595
- .command(require("../cmd/operations/affine"))
596
- .command(require("../cmd/channel-manipulation/bandbool"))
597
- .command(require("../cmd/operations/blur"))
598
- .command(require("../cmd/operations/boolean"))
599
- .command(require("../cmd/operations/clahe"))
600
- .command(require("../cmd/compositing/composite"))
601
- .command(require("../cmd/operations/convolve"))
602
- .command(require("../cmd/operations/dilate"))
603
- .command(require("../cmd/channel-manipulation/ensure-alpha"))
604
- .command(require("../cmd/operations/erode"))
605
- .command(require("../cmd/resizing/extend"))
606
- .command(require("../cmd/resizing/extract"))
607
- .command(require("../cmd/channel-manipulation/extract-channel"))
608
- .command(require("../cmd/operations/flatten"))
609
- .command(require("../cmd/operations/flip"))
610
- .command(require("../cmd/operations/flop"))
611
- .command(require("../cmd/operations/gamma"))
612
- .command(require("../cmd/colour-manipulation/greyscale"))
613
- .command(require("../cmd/channel-manipulation/join-channel"))
614
- .command(require("../cmd/operations/linear"))
615
- .command(require("../cmd/operations/median"))
616
- .command(require("../cmd/operations/modulate"))
617
- .command(require("../cmd/operations/negate"))
618
- .command(require("../cmd/operations/normalise"))
619
- .command(require("../cmd/colour-manipulation/pipeline-colourspace"))
620
- .command(require("../cmd/operations/recomb"))
621
- .command(require("../cmd/channel-manipulation/remove-alpha"))
622
- .command(require("../cmd/resizing/resize"))
623
- .command(require("../cmd/operations/rotate"))
624
- .command(require("../cmd/operations/sharpen"))
625
- .command(require("../cmd/operations/threshold"))
626
- .command(require("../cmd/colour-manipulation/tint"))
627
- .command(require("../cmd/output"))
628
- .command(require("../cmd/colour-manipulation/tocolourspace"))
629
- .command(require("../cmd/resizing/trim"))
630
- .command(require("../cmd/operations/unflatten"));
631
-
632
- // Helpers.
633
- const originalParse = cli.parse.bind(cli);
634
- const promisifiedParse = (...args) => {
635
- return new Promise((resolve, reject) => {
636
- originalParse(...args, (err, argv, output) => {
637
- if (err) {
638
- reject(err);
639
- }
640
- if (argv.v || argv.help) {
641
- reject(output);
642
- }
722
+ .command(affine)
723
+ .command(bandbool)
724
+ .command(blur)
725
+ .command(boolean)
726
+ .command(clahe)
727
+ .command(composite)
728
+ .command(convolve)
729
+ .command(dilate)
730
+ .command(ensureAlpha)
731
+ .command(erode)
732
+ .command(extend)
733
+ .command(extract)
734
+ .command(extractChannel)
735
+ .command(flatten)
736
+ .command(flip)
737
+ .command(flop)
738
+ .command(gamma)
739
+ .command(greyscale)
740
+ .command(joinChannel)
741
+ .command(linear)
742
+ .command(median)
743
+ .command(modulate)
744
+ .command(negate)
745
+ .command(normalise)
746
+ .command(pipelineColourspace)
747
+ .command(recomb)
748
+ .command(removeAlpha)
749
+ .command(resize)
750
+ .command(rotate)
751
+ .command(sharpen)
752
+ .command(threshold)
753
+ .command(tint)
754
+ .command(tile)
755
+ .command(toColourspace)
756
+ .command(trim)
757
+ .command(unflatten);
758
+
759
+ // Intercept parsing as to orchestrate commands.
760
+ cli.parseAsync = async function (args, context = createContext()) {
761
+ // Capture parsing result as a promise.
762
+ const argv = await new Promise((resolve, reject) => {
763
+ return cli.parse(args, context, (err, argv, output) => {
764
+ if (err) reject(err);
765
+ if (argv.help || argv.v) reject(output);
643
766
  resolve(argv);
644
767
  });
645
768
  });
646
- };
647
769
 
648
- // Exports.
649
- module.exports = cli;
650
- module.exports.inputOptions = Object.keys(inputOptions);
651
- module.exports.parse = function recursiveParse(args, context = {}) {
652
- return promisifiedParse(args, context).then((argv) => {
653
- // Handle arguments.
654
- // NOTE Use queue.unshift to apply global options first.
655
-
656
- // Global options.
657
-
658
- // Require at least one input file.
659
- // NOTE: check here b/c https://github.com/yargs/yargs/issues/403
660
- if (argv.input && argv.input.length === 0) {
661
- throw new Error("Not enough arguments following: i, input");
662
- }
663
-
664
- // @see https://sharp.pixelplumbing.com/api-output#timeout
665
- if (argv.timeout) {
666
- queue.unshift([
667
- "timeout",
668
- (sharp) => sharp.timeout({ seconds: argv.timeout }),
669
- ]);
670
- }
671
-
672
- // Output options.
673
-
674
- // @see https://sharp.pixelplumbing.com/api-output#toformat
675
- if (argv.format) {
676
- queue.unshift([
677
- "format",
678
- (sharp) =>
679
- sharp.toFormat(argv.format, { compression: argv.hcompression }),
680
- ]);
681
- }
682
-
683
- // @see https://sharp.pixelplumbing.com/api-output#withmetadata
684
- if (argv.metadata) {
685
- queue.unshift([
686
- "withMetadata",
687
- (sharp) => sharp.withMetadata(argv.metadata),
688
- ]);
689
- }
690
-
691
- // @see https://sharp.pixelplumbing.com/api-output#heif
692
- const { heif } = sharp.format;
693
- if (
694
- argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific.
695
- // Ensure libheif is installed before applying generic options.
696
- (heif.input &&
697
- heif.input.file &&
698
- (argv.effort !== undefined ||
699
- argv.hbitdepth ||
700
- argv.lossless ||
701
- argv.quality))
702
- ) {
703
- queue.unshift([
704
- "heif",
705
- (sharp) => {
706
- return sharp.heif({
707
- bitdepth: argv.hbitdepth,
708
- compression: argv.hcompression,
709
- effort: argv.effort,
710
- force: false,
711
- lossless: argv.lossless,
712
- quality: argv.quality,
713
- });
714
- },
715
- ]);
716
- }
717
-
718
- // @see https://sharp.pixelplumbing.com/api-output#avif
719
- if (
720
- argv.chromaSubsampling ||
721
- argv.effort !== undefined ||
722
- argv.lossless ||
723
- argv.quality
724
- ) {
725
- queue.unshift([
726
- "avif",
727
- (sharp) => {
728
- return sharp.avif({
729
- chromaSubsampling: argv.chromaSubsampling,
730
- effort: argv.effort,
731
- force: false,
732
- lossless: argv.lossless,
733
- quality: argv.quality,
734
- });
735
- },
736
- ]);
737
- }
738
-
739
- // @see https://sharp.pixelplumbing.com/api-output#gif
740
- if (
741
- argv.colors ||
742
- argv.effort !== undefined ||
743
- argv.dither !== undefined ||
744
- argv.interFrameMaxError ||
745
- argv.interPaletteMaxError ||
746
- argv.keepDuplicateFrames ||
747
- argv.loop ||
748
- argv.delay !== undefined ||
749
- argv.progressive ||
750
- argv.reuse
751
- ) {
752
- queue.unshift([
753
- "gif",
754
- (sharp) => {
755
- return sharp.gif({
756
- colors: argv.colors,
757
- force: false,
758
- effort: argv.effort,
759
- dither: argv.dither,
760
- interFrameMaxError: argv.interFrameMaxError,
761
- interPaletteMaxError: argv.interPaletteMaxError,
762
- keepDuplicateFrames: argv.keepDuplicateFrames,
763
- loop: argv.loop,
764
- delay: argv.delay,
765
- progressive: argv.progressive,
766
- reuse: argv.reuse,
767
- });
768
- },
769
- ]);
770
- }
771
-
772
- // @see https://sharp.pixelplumbing.com/api-output#jpeg
773
- if (
774
- argv.chromaSubsampling ||
775
- argv.mozjpeg ||
776
- argv.optimise ||
777
- argv.optimiseCoding !== true ||
778
- argv.optimiseScans ||
779
- argv.overshootDeringing ||
780
- argv.progressive ||
781
- argv.quantisationTable ||
782
- argv.quality ||
783
- argv.trellisQuantisation
784
- ) {
785
- queue.unshift([
786
- "jpeg",
787
- (sharp) => {
788
- return sharp.jpeg({
789
- chromaSubsampling: argv.chromaSubsampling,
790
- force: false,
791
- mozjpeg: argv.mozjpeg,
792
- optimiseCoding: argv.optimiseCoding,
793
- optimiseScans: argv.optimise || argv.optimiseScans,
794
- overshootDeringing: argv.optimise || argv.overshootDeringing,
795
- progressive: argv.progressive,
796
- quality: argv.quality,
797
- quantisationTable: argv.quantisationTable,
798
- trellisQuantisation: argv.optimise || argv.trellisQuantisation,
799
- });
800
- },
801
- ]);
802
- }
803
-
804
- // @see https://sharp.pixelplumbing.com/api-output#png
805
- if (
806
- argv.adaptiveFiltering ||
807
- argv.colors ||
808
- argv.compressionLevel !== undefined ||
809
- argv.dither !== undefined ||
810
- argv.effort ||
811
- argv.palette ||
812
- argv.progressive
813
- ) {
814
- queue.unshift([
815
- "png",
816
- (sharp) => {
817
- return sharp.png({
818
- adaptiveFiltering: argv.adaptiveFiltering,
819
- colors: argv.colors,
820
- compressionLevel: argv.compressionLevel,
821
- dither: argv.dither,
822
- effort: argv.effort,
823
- force: false,
824
- palette: argv.palette,
825
- progressive: argv.progressive,
826
- });
827
- },
828
- ]);
829
- }
830
-
831
- // @see https://sharp.pixelplumbing.com/api-output#tiff
832
- if (
833
- argv.bigtiff ||
834
- argv.bitdepth ||
835
- argv.compression !== optimizationOptions.compression.default ||
836
- argv.predictor !== optimizationOptions.predictor.default ||
837
- argv.miniswhite ||
838
- argv.pyramid ||
839
- argv.quality ||
840
- argv.resolutionUnit ||
841
- argv.tileBackground ||
842
- argv.tileHeight ||
843
- argv.tileWidth ||
844
- argv.xres ||
845
- argv.yres
846
- ) {
847
- queue.unshift([
848
- "tiff",
849
- (sharp) => {
850
- return sharp.tiff({
851
- background: argv.tileBackground,
852
- bigtiff: argv.bigtiff,
853
- bitdepth: argv.bitdepth,
854
- compression: argv.compression,
855
- force: false,
856
- miniswhite: argv.miniswhite,
857
- predictor: argv.predictor,
858
- pyramid: argv.pyramid,
859
- quality: argv.quality,
860
- resolutionUnit: argv.resolutionUnit,
861
- tile: argv.tileWidth !== undefined || argv.tileHeight !== undefined,
862
- tileHeight: argv.tileHeight || argv.tileWidth,
863
- tileWidth: argv.tileWidth || argv.tileHeight,
864
- xres: argv.xres,
865
- yres: argv.yres,
866
- });
867
- },
868
- ]);
869
- }
870
-
871
- // @see https://sharp.pixelplumbing.com/api-output#webp
872
- if (
873
- argv.alphaQuality ||
874
- argv.quality ||
875
- argv.lossless ||
876
- argv.minSize ||
877
- argv.mixed ||
878
- argv.nearLossless ||
879
- argv.effort !== undefined ||
880
- argv.preset !== optimizationOptions.preset.default ||
881
- argv.smartDeblock ||
882
- argv.smartSubsample
883
- ) {
884
- queue.unshift([
885
- "webp",
886
- (sharp) => {
887
- return sharp.webp({
888
- alphaQuality: argv.alphaQuality,
889
- effort: argv.effort,
890
- force: false,
891
- lossless: argv.lossless,
892
- minSize: argv.minSize,
893
- mixed: argv.mixed,
894
- nearLossless: argv.nearLossless,
895
- preset: argv.preset,
896
- quality: argv.quality,
897
- smartDeblock: argv.smartDeblock,
898
- smartSubsample: argv.smartSubsample,
899
- });
900
- },
901
- ]);
902
- }
903
-
904
- // Invoke with remaining arguments (if any).
905
- const { "--": remainingargv = [] } = argv;
906
- if (remainingargv.length > 0) {
907
- return recursiveParse(remainingargv, {
908
- ...context,
909
- ...pick(argv, Object.keys(options)), // Retain options.
910
- });
911
- }
912
- return argv;
913
- });
770
+ // Invoke with remaining arguments (if any). Carry over global options.
771
+ const remainingArgv = argv["--"] ?? [];
772
+ if (remainingArgv.length > 0) {
773
+ const globalArgv = pick(argv, Object.keys(options));
774
+ return cli.default(globalArgv).parseAsync(remainingArgv, context);
775
+ }
776
+
777
+ // Apply global options (once).
778
+ const queue = context["#queue"];
779
+
780
+ // @see https://sharp.pixelplumbing.com/api-output#timeout
781
+ if (argv.timeout) {
782
+ queue.unshift([
783
+ "timeout",
784
+ (sharp) => sharp.timeout({ seconds: argv.timeout }),
785
+ ]);
786
+ }
787
+
788
+ // Output options.
789
+
790
+ // @see https://sharp.pixelplumbing.com/api-output#toformat
791
+ if (argv.format) {
792
+ queue.unshift([
793
+ "format",
794
+ (sharp) =>
795
+ sharp.toFormat(argv.format, { compression: argv.hcompression }),
796
+ ]);
797
+ }
798
+
799
+ // @see https://sharp.pixelplumbing.com/api-output#keepgainmap
800
+ if (argv.keepGainMap) {
801
+ queue.unshift(["keepGainMap", (sharp) => sharp.keepGainMap()]);
802
+ }
803
+
804
+ // @see https://sharp.pixelplumbing.com/api-output#withmetadata
805
+ if (argv.metadata) {
806
+ queue.unshift([
807
+ "withMetadata",
808
+ (sharp) => sharp.withMetadata(argv.metadata),
809
+ ]);
810
+ }
811
+
812
+ // @see https://sharp.pixelplumbing.com/api-output#withdensity
813
+ if (argv.withDensity !== undefined) {
814
+ queue.unshift([
815
+ "withDensity",
816
+ (sharp) => sharp.withDensity(argv.withDensity),
817
+ ]);
818
+ }
819
+
820
+ // @see https://sharp.pixelplumbing.com/api-output#withgainmap
821
+ if (argv.withGainMap) {
822
+ queue.unshift(["withGainMap", (sharp) => sharp.withGainMap()]);
823
+ }
824
+
825
+ // @see https://sharp.pixelplumbing.com/api-output#heif
826
+ const { heif } = sharp.format;
827
+ if (
828
+ argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific.
829
+ // Ensure libheif is installed before applying generic options.
830
+ (heif.input &&
831
+ heif.input.file &&
832
+ (argv.effort !== undefined ||
833
+ argv.hbitdepth ||
834
+ argv.lossless ||
835
+ argv.quality ||
836
+ argv.tune))
837
+ ) {
838
+ queue.unshift([
839
+ "heif",
840
+ (sharp, { format } = {}) => {
841
+ if (format && format !== "heif") return sharp;
842
+ return sharp.heif({
843
+ bitdepth: argv.hbitdepth,
844
+ compression: argv.hcompression,
845
+ effort: argv.effort,
846
+ force: false,
847
+ lossless: argv.lossless,
848
+ quality: argv.quality,
849
+ tune: argv.tune,
850
+ });
851
+ },
852
+ ]);
853
+ }
854
+
855
+ // @see https://sharp.pixelplumbing.com/api-output#avif
856
+ if (
857
+ argv.chromaSubsampling ||
858
+ argv.effort !== undefined ||
859
+ argv.lossless ||
860
+ argv.quality ||
861
+ argv.tune
862
+ ) {
863
+ queue.unshift([
864
+ "avif",
865
+ (sharp, { format } = {}) => {
866
+ if (format && format !== "avif") return sharp;
867
+ return sharp.avif({
868
+ chromaSubsampling: argv.chromaSubsampling,
869
+ effort: argv.effort,
870
+ force: false,
871
+ lossless: argv.lossless,
872
+ quality: argv.quality,
873
+ tune: argv.tune,
874
+ });
875
+ },
876
+ ]);
877
+ }
878
+
879
+ // @see https://sharp.pixelplumbing.com/api-output#gif
880
+ if (
881
+ argv.colors ||
882
+ argv.effort !== undefined ||
883
+ argv.dither !== undefined ||
884
+ argv.interFrameMaxError ||
885
+ argv.interPaletteMaxError ||
886
+ argv.keepDuplicateFrames ||
887
+ argv.loop ||
888
+ argv.delay !== undefined ||
889
+ argv.progressive ||
890
+ argv.reuse
891
+ ) {
892
+ queue.unshift([
893
+ "gif",
894
+ (sharp, { format } = {}) => {
895
+ if (format && format !== "gif") return sharp;
896
+ return sharp.gif({
897
+ colors: argv.colors,
898
+ force: false,
899
+ effort: argv.effort,
900
+ dither: argv.dither,
901
+ interFrameMaxError: argv.interFrameMaxError,
902
+ interPaletteMaxError: argv.interPaletteMaxError,
903
+ keepDuplicateFrames: argv.keepDuplicateFrames,
904
+ loop: argv.loop,
905
+ delay: argv.delay,
906
+ progressive: argv.progressive,
907
+ reuse: argv.reuse,
908
+ });
909
+ },
910
+ ]);
911
+ }
912
+
913
+ // @see https://sharp.pixelplumbing.com/api-output#jpeg
914
+ if (
915
+ argv.chromaSubsampling ||
916
+ argv.mozjpeg ||
917
+ argv.optimise ||
918
+ argv.optimiseCoding !== true ||
919
+ argv.optimiseScans ||
920
+ argv.overshootDeringing ||
921
+ argv.progressive ||
922
+ argv.quantisationTable ||
923
+ argv.quality ||
924
+ argv.trellisQuantisation
925
+ ) {
926
+ queue.unshift([
927
+ "jpeg",
928
+ (sharp, { format } = {}) => {
929
+ if (format && format !== "jpeg") return sharp;
930
+ return sharp.jpeg({
931
+ chromaSubsampling: argv.chromaSubsampling,
932
+ force: false,
933
+ mozjpeg: argv.mozjpeg,
934
+ optimiseCoding: argv.optimiseCoding,
935
+ optimiseScans: argv.optimise || argv.optimiseScans,
936
+ overshootDeringing: argv.optimise || argv.overshootDeringing,
937
+ progressive: argv.progressive,
938
+ quality: argv.quality,
939
+ quantisationTable: argv.quantisationTable,
940
+ trellisQuantisation: argv.optimise || argv.trellisQuantisation,
941
+ });
942
+ },
943
+ ]);
944
+ }
945
+
946
+ // @see https://sharp.pixelplumbing.com/api-output#png
947
+ if (
948
+ argv.adaptiveFiltering ||
949
+ argv.colors ||
950
+ argv.compressionLevel !== undefined ||
951
+ argv.dither !== undefined ||
952
+ argv.effort ||
953
+ argv.palette ||
954
+ argv.progressive
955
+ ) {
956
+ queue.unshift([
957
+ "png",
958
+ (sharp, { format } = {}) => {
959
+ if (format && format !== "png") return sharp;
960
+ return sharp.png({
961
+ adaptiveFiltering: argv.adaptiveFiltering,
962
+ colors: argv.colors,
963
+ compressionLevel: argv.compressionLevel,
964
+ dither: argv.dither,
965
+ effort: argv.effort,
966
+ force: false,
967
+ palette: argv.palette,
968
+ progressive: argv.progressive,
969
+ });
970
+ },
971
+ ]);
972
+ }
973
+
974
+ // @see https://sharp.pixelplumbing.com/api-output#tiff
975
+ if (
976
+ argv.bigtiff ||
977
+ argv.bitdepth ||
978
+ argv.compression !== optimizationOptions.compression.default ||
979
+ argv.predictor !== optimizationOptions.predictor.default ||
980
+ argv.miniswhite ||
981
+ argv.pyramid ||
982
+ argv.quality ||
983
+ argv.resolutionUnit ||
984
+ argv.tileBackground ||
985
+ argv.tileHeight ||
986
+ argv.tileWidth ||
987
+ argv.xres ||
988
+ argv.yres
989
+ ) {
990
+ queue.unshift([
991
+ "tiff",
992
+ (sharp, { format } = {}) => {
993
+ if (format && format !== "tiff") return sharp;
994
+ return sharp.tiff({
995
+ background: argv.tileBackground,
996
+ bigtiff: argv.bigtiff,
997
+ bitdepth: argv.bitdepth,
998
+ compression: argv.compression,
999
+ force: false,
1000
+ miniswhite: argv.miniswhite,
1001
+ predictor: argv.predictor,
1002
+ pyramid: argv.pyramid,
1003
+ quality: argv.quality,
1004
+ resolutionUnit: argv.resolutionUnit,
1005
+ tile: argv.tileWidth !== undefined || argv.tileHeight !== undefined,
1006
+ tileHeight: argv.tileHeight || argv.tileWidth,
1007
+ tileWidth: argv.tileWidth || argv.tileHeight,
1008
+ xres: argv.xres,
1009
+ yres: argv.yres,
1010
+ });
1011
+ },
1012
+ ]);
1013
+ }
1014
+
1015
+ // @see https://sharp.pixelplumbing.com/api-output#webp
1016
+ if (
1017
+ argv.alphaQuality ||
1018
+ argv.quality ||
1019
+ argv.lossless ||
1020
+ argv.minSize ||
1021
+ argv.mixed ||
1022
+ argv.nearLossless ||
1023
+ argv.effort !== undefined ||
1024
+ argv.exact ||
1025
+ argv.preset !== optimizationOptions.preset.default ||
1026
+ argv.smartDeblock ||
1027
+ argv.smartSubsample
1028
+ ) {
1029
+ queue.unshift([
1030
+ "webp",
1031
+ (sharp, { format } = {}) => {
1032
+ if (format && format !== "webp") return sharp;
1033
+ return sharp.webp({
1034
+ alphaQuality: argv.alphaQuality,
1035
+ effort: argv.effort,
1036
+ exact: argv.exact,
1037
+ force: false,
1038
+ lossless: argv.lossless,
1039
+ minSize: argv.minSize,
1040
+ mixed: argv.mixed,
1041
+ nearLossless: argv.nearLossless,
1042
+ preset: argv.preset,
1043
+ quality: argv.quality,
1044
+ smartDeblock: argv.smartDeblock,
1045
+ smartSubsample: argv.smartSubsample,
1046
+ });
1047
+ },
1048
+ ]);
1049
+ }
1050
+
1051
+ return argv;
914
1052
  };
1053
+
1054
+ export default cli;