Skip to content

Commit 65e3a78

Browse files
Mike-Daxm-allanson
authored andcommitted
feat(remark-images): Added support for WebP versions in addition to fallbacks. (#6495)
* feat(remark): Added support for WebP versions in addition to fallbacks. * Added whitespace to match the snapshot tests. * Modified snapshot files to pass. * More whitespace matching.
1 parent a49f240 commit 65e3a78

File tree

5 files changed

+93
-16
lines changed

5 files changed

+93
-16
lines changed

packages/gatsby-plugin-sharp/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ plugin for Markdown content as gatsby-remark-images).
9090
- `aspectRatio` (float)
9191
- `src` (string)
9292
- `srcSet` (string)
93+
- `srcSetType` (string)
9394
- `sizes` (string)
9495
- `originalImg` (string)
9596

packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Object {
2323
"src": "/static/test-1234-85b96.png",
2424
"srcSet": "/static/test-1234-7c9f5.png 200w,
2525
/static/test-1234-85b96.png 281w",
26+
"srcSetType": "image/png",
2627
}
2728
`;
2829

@@ -39,6 +40,7 @@ Object {
3940
"src": "/static/test-1234-24ad8.png",
4041
"srcSet": "/static/test-1234-06d78.png 200w,
4142
/static/test-1234-24ad8.png 281w",
43+
"srcSetType": "image/png",
4244
}
4345
`;
4446

@@ -54,6 +56,7 @@ Object {
5456
"sizes": "(max-width: 1px) 100vw, 1px",
5557
"src": "/static/test-1234-18c2a.png",
5658
"srcSet": "/static/test-1234-18c2a.png 1w",
59+
"srcSetType": "image/png",
5760
}
5861
`;
5962

packages/gatsby-plugin-sharp/src/index.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ async function fluid({ file, args = {}, reporter }) {
450450
return null
451451
}
452452

453-
const { width, height, density } = metadata
453+
const { width, height, density, format } = metadata
454454
const pixelRatio =
455455
options.sizeByPixelDensity && typeof density === `number` && density > 0
456456
? density / 72
@@ -533,11 +533,33 @@ async function fluid({ file, args = {}, reporter }) {
533533
.join(`,\n`)
534534
const originalName = file.base
535535

536+
// figure out the srcSet format
537+
let srcSetType = `image/${format}`
538+
539+
if (options.toFormat) {
540+
switch (options.toFormat) {
541+
case `png`:
542+
srcSetType = `image/png`
543+
break
544+
case `jpg`:
545+
srcSetType = `image/jpeg`
546+
break
547+
case `webp`:
548+
srcSetType = `image/webp`
549+
break
550+
case ``:
551+
case `no_change`:
552+
default:
553+
break
554+
}
555+
}
556+
536557
return {
537558
base64: base64Image.src,
538559
aspectRatio: images[0].aspectRatio,
539560
src: fallbackSrc,
540561
srcSet,
562+
srcSetType,
541563
sizes: options.sizes,
542564
originalImg: originalImg,
543565
originalName: originalName,

packages/gatsby-remark-images/README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ plugins: [
5050
| `linkImagesToOriginal` | `true` | Add a link to each image to the original image. Sometimes people want to see a full-sized version of an image e.g. to see extra detail on a part of the image and this is a convenient and common pattern for enabling this. Set this option to false to disable this behavior. |
5151
| `showCaptions` | `false` | Add a caption to each image with the contents of the title attribute, when this is not empty. Set this option to true to enable this behavior. |
5252
| `sizeByPixelDensity` | `false` | Analyze images' pixel density to make decisions about target image size. This is what GitHub is doing when embedding images in tickets. This is a useful setting for documentation pages with a lot of screenshots. It can have unintended side effects on high pixel density artworks.<br/><br/>Example: A screenshot made on a retina screen with a resolution of 144 (e.g. Macbook) and a width of 100px, will be rendered at 50px. |
53-
| `wrapperStyle` | | Add custom styles to the div wrapping the responsive images. Use the syntax for the style attribute e.g. `margin-bottom:10px; background: red;` |
54-
| `backgroundColor` | `white` | Set the background color of the image to match the background image of your design |
53+
| `wrapperStyle` | | Add custom styles to the div wrapping the responsive images. Use the syntax for the style attribute e.g. `margin-bottom:10px; background: red;`. |
54+
| `backgroundColor` | `white` | Set the background color of the image to match the background image of your design. |
55+
| `quality` | `50` | The quality level of the generated files. |
56+
| `withWebp` | `false` | Additionally generate WebP versions alongside your chosen file format. They are added as a srcset with the appropriate mimetype and will be loaded in browsers that support the format. Pass `true` for default support, or an object of options to specifically override those for the WebP files. For example, pass `{ quality: 80 }` to have the WebP images be at quality level 80. |
5557

5658
[1]: https://jmperezperez.com/medium-image-progressive-loading-placeholder/
5759
[2]: https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/

packages/gatsby-remark-images/src/index.js

+62-13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = (
2424
linkImagesToOriginal: true,
2525
showCaptions: false,
2626
pathPrefix,
27+
withWebp: false,
2728
}
2829

2930
const options = _.defaults(pluginOptions, defaults)
@@ -86,6 +87,66 @@ module.exports = (
8687
// Fade in images on load.
8788
// https://www.perpetual-beta.org/weblog/silky-smooth-image-loading.html
8889

90+
const imageClass = `gatsby-resp-image-image`
91+
const imageStyle = `width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px ${
92+
options.backgroundColor
93+
};`
94+
95+
// Create our base image tag
96+
let imageTag = `
97+
<img
98+
class="${imageClass}"
99+
style="${imageStyle}"
100+
alt="${node.alt ? node.alt : defaultAlt}"
101+
title="${node.title ? node.title : ``}"
102+
src="${fallbackSrc}"
103+
srcset="${srcSet}"
104+
sizes="${fluidResult.sizes}"
105+
/>
106+
`
107+
108+
// if options.withWebp is enabled, generate a webp version and change the image tag to a picture tag
109+
if (options.withWebp) {
110+
const webpFluidResult = await fluid({
111+
file: imageNode,
112+
args: _.defaults(
113+
{ toFormat: `WEBP` },
114+
// override options if it's an object, otherwise just pass through defaults
115+
options.withWebp === true ? {} : options.withWebp,
116+
pluginOptions,
117+
defaults
118+
),
119+
reporter,
120+
})
121+
122+
if (!webpFluidResult) {
123+
return resolve()
124+
}
125+
126+
imageTag = `
127+
<picture>
128+
<source
129+
srcset="${webpFluidResult.srcSet}"
130+
sizes="${webpFluidResult.sizes}"
131+
type="${webpFluidResult.srcSetType}"
132+
/>
133+
<source
134+
srcset="${srcSet}"
135+
sizes="${fluidResult.sizes}"
136+
type="${fluidResult.srcSetType}"
137+
/>
138+
<img
139+
class="${imageClass}"
140+
style="${imageStyle}"
141+
src="${fallbackSrc}"
142+
alt="${node.alt ? node.alt : defaultAlt}"
143+
title="${node.title ? node.title : ``}"
144+
src="${fallbackSrc}"
145+
/>
146+
</picture>
147+
`
148+
}
149+
89150
// Construct new image node w/ aspect ratio placeholder
90151
let rawHTML = `
91152
<span
@@ -99,19 +160,7 @@ module.exports = (
99160
style="padding-bottom: ${ratio}; position: relative; bottom: 0; left: 0; background-image: url('${
100161
fluidResult.base64
101162
}'); background-size: cover; display: block;"
102-
>
103-
<img
104-
class="gatsby-resp-image-image"
105-
style="width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px ${
106-
options.backgroundColor
107-
};"
108-
alt="${node.alt ? node.alt : defaultAlt}"
109-
title="${node.title ? node.title : ``}"
110-
src="${fallbackSrc}"
111-
srcset="${srcSet}"
112-
sizes="${fluidResult.sizes}"
113-
/>
114-
</span>
163+
>${imageTag}</span>
115164
</span>
116165
`
117166

0 commit comments

Comments
 (0)