Skip to content

Commit

Permalink
Fixes #260
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Dec 20, 2024
1 parent c795801 commit 777be8c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/global-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const DEFAULTS = {
statsOnly: false,
remoteImageMetadata: {}, // For `statsOnly` remote images, this needs to be populated with { width, height, format? }

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

hashLength: 10, // Truncates the hash to this length
Expand Down
27 changes: 25 additions & 2 deletions src/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ const FORMAT_ALIASES = {
"svg+xml": "svg",
};

const ANIMATED_TYPES = [
"webp",
"gif",
];


class Image {
#input;
Expand Down Expand Up @@ -185,7 +190,7 @@ class Image {
return valid.sort((a, b) => a - b);
}

static getFormatsArray(formats, autoFormat, svgShortCircuit) {
static getFormatsArray(formats, autoFormat, svgShortCircuit, isAnimated) {
if(formats && formats.length) {
if(typeof formats === "string") {
formats = formats.split(",");
Expand Down Expand Up @@ -216,6 +221,17 @@ class Image {
});
}

if(isAnimated) {
let validAnimatedFormats = formats.filter(f => ANIMATED_TYPES.includes(f));
// override formats if a valid animated format is found, otherwise leave as-is
if(validAnimatedFormats.length > 0) {
debug("Filtering non-animated formats from output: from %o to %o", formats, validAnimatedFormats);
formats = validAnimatedFormats;
} else {
debug("No animated output formats found for animated image, using static image instead.");
}
}

// Remove duplicates (e.g., if null happens to coincide with an explicit format
// or a user passes in multiple duplicate values)
formats = [...new Set(formats)];
Expand Down Expand Up @@ -426,11 +442,18 @@ class Image {
return orientation >= 5 && orientation <= 8;
}

isAnimated(metadata, options) {
// input has multiple pages: https://sharp.pixelplumbing.com/api-input#metadata
// sharp options have animated image support enabled
return metadata?.pages > 1 && options?.sharpOptions?.animated;
}

// metadata so far: width, height, format
// src is used to calculate the output file names
getFullStats(metadata) {
let results = [];
let outputFormats = Image.getFormatsArray(this.options.formats, metadata.format || this.options.overrideInputFormat, this.options.svgShortCircuit);
let isImageAnimated = this.isAnimated(metadata, this.options);
let outputFormats = Image.getFormatsArray(this.options.formats, metadata.format || this.options.overrideInputFormat, this.options.svgShortCircuit, isImageAnimated);

if (this.needsRotation(metadata.orientation)) {
[metadata.height, metadata.width] = [metadata.width, metadata.height];
Expand Down
37 changes: 37 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,7 @@ test("Animated gif", async t => {
sharpOptions: {
animated: true
},
useCache: false,
outputDir: "./test/img/",
});

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

test("Animated gif format filtering (no good ones)", async t => {
let stats = await eleventyImage("./test/earth-animated.gif", {
dryRun: true,
formats: ["jpeg"],
sharpOptions: {
animated: true
},
useCache: false,
});

t.deepEqual(Object.keys(stats), ["jpeg"]);
t.is(stats.jpeg.length, 1);
t.is(stats.jpeg[0].width, 400);
t.is(stats.jpeg[0].height, 400);
// it’s a big boi
t.true( stats.jpeg[0].size < 1000*999, `${stats.jpeg[0].size} size is too big, should be smaller than ${1000*999}.` );
});

test("Animated gif format filtering (one valid one)", async t => {
let stats = await eleventyImage("./test/earth-animated.gif", {
dryRun: true,
formats: ["jpeg", "gif"],
sharpOptions: {
animated: true
},
useCache: false,
});

t.deepEqual(Object.keys(stats), ["gif"]);
t.is(stats.gif.length, 1);
t.is(stats.gif[0].width, 400);
t.is(stats.gif[0].height, 400);
// it’s a big boi
t.true( stats.gif[0].size > 1000*999 );
});

test("Change hashLength", async t => {
let stats = await eleventyImage("./test/bio-2017.jpg", {
widths: [null],
Expand Down

0 comments on commit 777be8c

Please sign in to comment.