Skip to content

Commit e9345cd

Browse files
rgiesepieh
authored andcommitted
fix(gatsby-plugin-manifest): improve SVG->PNG fidelity (#11608)
## Description `gatsby-plugin-manifest` resizes a user-provided icon to PNGs of various resolutions required for favicons using Sharp. This change allows SVGs to be usable as the user-provided icon. Sharp is already capable of ingesting an SVG and rasterizing it to PNGs; however, in its default configuration, it first rasterizes the provided SVG to a pixel image of default density (e.g. 72dpi) and then upscales it to the desired size (e.g. 512x512), which can create really poor upscaling artifacts. This change instructs Sharp to use a rasterizing density equal to the size of the desired output image which eliminates the upscaling problems.
1 parent a82682c commit e9345cd

File tree

3 files changed

+10
-4
lines changed

3 files changed

+10
-4
lines changed

packages/gatsby-plugin-manifest/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This plugin configures Gatsby to create a `manifest.webmanifest` file on every s
2727

2828
## Generating icons
2929

30-
It can be tedious creating the multitude of icon sizes required by different devices and browsers. This plugin includes code to auto-generate smaller icons from a larger src image.
30+
It can be tedious creating the multitude of icon sizes required by different devices and browsers. This plugin includes code to auto-generate smaller icons from a larger src image (which can also be an SVG).
3131

3232
There are three modes in which icon generation can function: automatic, hybrid, and manual. These three modes are explained below. Icon generation functions differently depending on which of the three you choose.
3333

packages/gatsby-plugin-manifest/src/__tests__/gatsby-node.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ describe(`Test plugin manifest options`, () => {
5757
fs.statSync.mockReturnValueOnce({ isFile: () => true })
5858

5959
const icon = `pretend/this/exists.png`
60+
const size = 48
6061

6162
await onPostBootstrap([], {
6263
name: `GatsbyJS`,
@@ -69,13 +70,13 @@ describe(`Test plugin manifest options`, () => {
6970
icons: [
7071
{
7172
src: `icons/icon-48x48.png`,
72-
sizes: `48x48`,
73+
sizes: `${size}x${size}`,
7374
type: `image/png`,
7475
},
7576
],
7677
})
7778

78-
expect(sharp).toHaveBeenCalledWith(icon)
79+
expect(sharp).toHaveBeenCalledWith(icon, { density: size })
7980
})
8081

8182
it(`fails on non existing icon`, done => {

packages/gatsby-plugin-manifest/src/gatsby-node.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ function generateIcons(icons, srcIcon) {
1111
const size = parseInt(icon.sizes.substring(0, icon.sizes.lastIndexOf(`x`)))
1212
const imgPath = path.join(`public`, icon.src)
1313

14-
return sharp(srcIcon)
14+
// For vector graphics, instruct sharp to use a pixel density
15+
// suitable for the resolution we're rasterizing to.
16+
// For pixel graphics sources this has no effect.
17+
// Sharp accept density from 1 to 2400
18+
const density = Math.min(2400, Math.max(1, size))
19+
return sharp(srcIcon, { density })
1520
.resize(size)
1621
.toFile(imgPath)
1722
.then(() => {})

0 commit comments

Comments
 (0)