Skip to content

Commit 777be8c

Browse files
committed
Fixes #260
1 parent c795801 commit 777be8c

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

src/global-options.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const DEFAULTS = {
5454
statsOnly: false,
5555
remoteImageMetadata: {}, // For `statsOnly` remote images, this needs to be populated with { width, height, format? }
5656

57-
useCache: true, // in-memory cache
57+
useCache: true, // in-memory and disk cache
5858
dryRun: false, // Also returns a buffer instance in the return object. Doesn’t write anything to the file system
5959

6060
hashLength: 10, // Truncates the hash to this length

src/image.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ const FORMAT_ALIASES = {
3232
"svg+xml": "svg",
3333
};
3434

35+
const ANIMATED_TYPES = [
36+
"webp",
37+
"gif",
38+
];
39+
3540

3641
class Image {
3742
#input;
@@ -185,7 +190,7 @@ class Image {
185190
return valid.sort((a, b) => a - b);
186191
}
187192

188-
static getFormatsArray(formats, autoFormat, svgShortCircuit) {
193+
static getFormatsArray(formats, autoFormat, svgShortCircuit, isAnimated) {
189194
if(formats && formats.length) {
190195
if(typeof formats === "string") {
191196
formats = formats.split(",");
@@ -216,6 +221,17 @@ class Image {
216221
});
217222
}
218223

224+
if(isAnimated) {
225+
let validAnimatedFormats = formats.filter(f => ANIMATED_TYPES.includes(f));
226+
// override formats if a valid animated format is found, otherwise leave as-is
227+
if(validAnimatedFormats.length > 0) {
228+
debug("Filtering non-animated formats from output: from %o to %o", formats, validAnimatedFormats);
229+
formats = validAnimatedFormats;
230+
} else {
231+
debug("No animated output formats found for animated image, using static image instead.");
232+
}
233+
}
234+
219235
// Remove duplicates (e.g., if null happens to coincide with an explicit format
220236
// or a user passes in multiple duplicate values)
221237
formats = [...new Set(formats)];
@@ -426,11 +442,18 @@ class Image {
426442
return orientation >= 5 && orientation <= 8;
427443
}
428444

445+
isAnimated(metadata, options) {
446+
// input has multiple pages: https://sharp.pixelplumbing.com/api-input#metadata
447+
// sharp options have animated image support enabled
448+
return metadata?.pages > 1 && options?.sharpOptions?.animated;
449+
}
450+
429451
// metadata so far: width, height, format
430452
// src is used to calculate the output file names
431453
getFullStats(metadata) {
432454
let results = [];
433-
let outputFormats = Image.getFormatsArray(this.options.formats, metadata.format || this.options.overrideInputFormat, this.options.svgShortCircuit);
455+
let isImageAnimated = this.isAnimated(metadata, this.options);
456+
let outputFormats = Image.getFormatsArray(this.options.formats, metadata.format || this.options.overrideInputFormat, this.options.svgShortCircuit, isImageAnimated);
434457

435458
if (this.needsRotation(metadata.orientation)) {
436459
[metadata.height, metadata.width] = [metadata.width, metadata.height];

test/test.js

+37
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ test("Animated gif", async t => {
10651065
sharpOptions: {
10661066
animated: true
10671067
},
1068+
useCache: false,
10681069
outputDir: "./test/img/",
10691070
});
10701071

@@ -1075,6 +1076,42 @@ test("Animated gif", async t => {
10751076
t.true( stats.gif[0].size > 1000*999 );
10761077
});
10771078

1079+
test("Animated gif format filtering (no good ones)", async t => {
1080+
let stats = await eleventyImage("./test/earth-animated.gif", {
1081+
dryRun: true,
1082+
formats: ["jpeg"],
1083+
sharpOptions: {
1084+
animated: true
1085+
},
1086+
useCache: false,
1087+
});
1088+
1089+
t.deepEqual(Object.keys(stats), ["jpeg"]);
1090+
t.is(stats.jpeg.length, 1);
1091+
t.is(stats.jpeg[0].width, 400);
1092+
t.is(stats.jpeg[0].height, 400);
1093+
// it’s a big boi
1094+
t.true( stats.jpeg[0].size < 1000*999, `${stats.jpeg[0].size} size is too big, should be smaller than ${1000*999}.` );
1095+
});
1096+
1097+
test("Animated gif format filtering (one valid one)", async t => {
1098+
let stats = await eleventyImage("./test/earth-animated.gif", {
1099+
dryRun: true,
1100+
formats: ["jpeg", "gif"],
1101+
sharpOptions: {
1102+
animated: true
1103+
},
1104+
useCache: false,
1105+
});
1106+
1107+
t.deepEqual(Object.keys(stats), ["gif"]);
1108+
t.is(stats.gif.length, 1);
1109+
t.is(stats.gif[0].width, 400);
1110+
t.is(stats.gif[0].height, 400);
1111+
// it’s a big boi
1112+
t.true( stats.gif[0].size > 1000*999 );
1113+
});
1114+
10781115
test("Change hashLength", async t => {
10791116
let stats = await eleventyImage("./test/bio-2017.jpg", {
10801117
widths: [null],

0 commit comments

Comments
 (0)