1
1
/* eslint-disable no-unused-expressions */
2
2
import { stripIndent } from "common-tags"
3
+ import camelCase from "camelcase"
3
4
import { IGatsbyImageData } from "."
4
5
5
6
const DEFAULT_PIXEL_DENSITIES = [ 0.25 , 0.5 , 1 , 2 ]
@@ -19,7 +20,8 @@ export const EVERY_BREAKPOINT = [
19
20
4096 ,
20
21
]
21
22
const DEFAULT_FLUID_WIDTH = 800
22
- const DEFAULT_FIXED_WIDTH = 400
23
+ const DEFAULT_FIXED_WIDTH = 800
24
+ const DEFAULT_ASPECT_RATIO = 4 / 3
23
25
24
26
export type Fit = "cover" | "fill" | "inside" | "outside" | "contain"
25
27
@@ -107,6 +109,8 @@ export interface IGatsbyImageHelperArgs {
107
109
fit ?: Fit
108
110
options ?: Record < string , unknown >
109
111
breakpoints ?: Array < number >
112
+ backgroundColor ?: string
113
+ aspectRatio ?: number
110
114
}
111
115
112
116
const warn = ( message : string ) : void => console . warn ( message )
@@ -150,20 +154,68 @@ export function formatFromFilename(filename: string): ImageFormat | undefined {
150
154
return undefined
151
155
}
152
156
157
+ export function setDefaultDimensions (
158
+ args : IGatsbyImageHelperArgs
159
+ ) : IGatsbyImageHelperArgs {
160
+ let {
161
+ layout = `constrained` ,
162
+ width,
163
+ height,
164
+ sourceMetadata,
165
+ breakpoints,
166
+ aspectRatio,
167
+ formats = [ `auto` , `webp` ] ,
168
+ } = args
169
+ formats = formats . map ( format => format . toLowerCase ( ) as ImageFormat )
170
+ layout = camelCase ( layout ) as Layout
171
+
172
+ if ( width && height ) {
173
+ return args
174
+ }
175
+ if ( sourceMetadata . width && sourceMetadata . height && ! aspectRatio ) {
176
+ aspectRatio = sourceMetadata . width / sourceMetadata . height
177
+ }
178
+
179
+ if ( layout === `fullWidth` ) {
180
+ width = width || sourceMetadata . width || breakpoints [ breakpoints . length - 1 ]
181
+ height = height || Math . round ( width / ( aspectRatio || DEFAULT_ASPECT_RATIO ) )
182
+ } else {
183
+ if ( ! width ) {
184
+ if ( height && aspectRatio ) {
185
+ width = height * aspectRatio
186
+ } else if ( sourceMetadata . width ) {
187
+ width = sourceMetadata . width
188
+ } else if ( height ) {
189
+ width = Math . round ( height / DEFAULT_ASPECT_RATIO )
190
+ } else {
191
+ width = DEFAULT_FIXED_WIDTH
192
+ }
193
+ }
194
+
195
+ if ( aspectRatio && ! height ) {
196
+ height = Math . round ( width / aspectRatio )
197
+ }
198
+ }
199
+ return { ...args , width, height, aspectRatio, layout, formats }
200
+ }
201
+
153
202
export function generateImageData (
154
203
args : IGatsbyImageHelperArgs
155
204
) : IGatsbyImageData {
205
+ args = setDefaultDimensions ( args )
206
+
156
207
let {
157
208
pluginName,
158
209
sourceMetadata,
159
210
generateImageSource,
160
- layout = `constrained` ,
211
+ layout,
161
212
fit,
162
213
options,
163
214
width,
164
215
height,
165
216
filename,
166
217
reporter = { warn } ,
218
+ backgroundColor,
167
219
} = args
168
220
169
221
if ( ! pluginName ) {
@@ -175,18 +227,19 @@ export function generateImageData(
175
227
if ( typeof generateImageSource !== `function` ) {
176
228
throw new Error ( `generateImageSource must be a function` )
177
229
}
230
+
178
231
if ( ! sourceMetadata || ( ! sourceMetadata . width && ! sourceMetadata . height ) ) {
179
232
// No metadata means we let the CDN handle max size etc, aspect ratio etc
180
233
sourceMetadata = {
181
234
width,
182
235
height,
183
- format : formatFromFilename ( filename ) ,
236
+ format : sourceMetadata ?. format || formatFromFilename ( filename ) || `auto` ,
184
237
}
185
238
} else if ( ! sourceMetadata . format ) {
186
239
sourceMetadata . format = formatFromFilename ( filename )
187
240
}
188
- //
189
- const formats = new Set < ImageFormat > ( args . formats || [ `auto` , `webp` ] )
241
+
242
+ const formats = new Set < ImageFormat > ( args . formats )
190
243
191
244
if ( formats . size === 0 || formats . has ( `auto` ) || formats . has ( `` ) ) {
192
245
formats . delete ( `auto` )
@@ -262,7 +315,11 @@ export function generateImageData(
262
315
}
263
316
} )
264
317
265
- const imageProps : Partial < IGatsbyImageData > = { images : result , layout }
318
+ const imageProps : Partial < IGatsbyImageData > = {
319
+ images : result ,
320
+ layout,
321
+ backgroundColor,
322
+ }
266
323
switch ( layout ) {
267
324
case `fixed` :
268
325
imageProps . width = imageSizes . presentationWidth
@@ -317,7 +374,7 @@ export function calculateImageSizes(args: IImageSizeArgs): IImageSizes {
317
374
return responsiveImageSizes ( { breakpoints, ...args } )
318
375
} else {
319
376
reporter . warn (
320
- `No valid layout was provided for the image at ${ filename } . Valid image layouts are fixed, fullWidth, and constrained.`
377
+ `No valid layout was provided for the image at ${ filename } . Valid image layouts are fixed, fullWidth, and constrained. Found ${ layout } `
321
378
)
322
379
return {
323
380
sizes : [ imgDimensions . width ] ,
0 commit comments