Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions src/runtime/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { hasProtocol, parseURL, joinURL, withLeadingSlash } from 'ufo'
import { imageMeta } from './utils/meta'
import { checkDensities, parseDensities, parseSize, parseSizes } from './utils'
import { prerenderStaticImages } from './utils/prerender'
import type { ImageOptions, ImageSizesOptions, CreateImageOptions, ResolvedImage, ImageCTX, $Img, ImageSizes, ImageSizesVariant, ConfiguredImageProviders } from '@nuxt/image'
import type { ImageOptions, CreateImageOptions, ResolvedImage, ImageCTX, $Img, ImageSizes, ImageSizesVariant, ConfiguredImageProviders } from '@nuxt/image'

export function createImage(globalOptions: CreateImageOptions) {
const ctx: ImageCTX = {
options: globalOptions,
}

const getImage: $Img['getImage'] = (input: string, options = {}) => {
const getImage = (input: string, options: ImageOptions<any> = {}): ResolvedImage => {
const image = resolveImage(ctx, input, options)

// Prerender static images
Expand All @@ -25,20 +25,20 @@ export function createImage(globalOptions: CreateImageOptions) {

for (const presetName in globalOptions.presets) {
$img[presetName] = ((source, modifiers, options) =>
$img(source, modifiers, { ...globalOptions.presets[presetName], ...options })) as $Img[string]
$img(source, modifiers, { ...globalOptions.presets[presetName], ...options } as ImageOptions<any>)) as $Img[string]
}

$img.options = globalOptions
$img.getImage = getImage
$img.getMeta = ((input: string, options?: ImageOptions) => getMeta(ctx, input, options)) as $Img['getMeta']
$img.getSizes = ((input: string, options: ImageSizesOptions) => getSizes(ctx, input, options)) as $Img['getSizes']
$img.getMeta = ((input: string, options?: ImageOptions<any>) => getMeta(ctx, input, options)) as $Img['getMeta']
$img.getSizes = ((input: string, options?: ImageOptions<any>) => getSizes(ctx, input, options)) as $Img['getSizes']

ctx.$img = $img as $Img

return $img
}

async function getMeta(ctx: ImageCTX, input: string, options?: ImageOptions) {
async function getMeta(ctx: ImageCTX, input: string, options?: ImageOptions<any>) {
const image = resolveImage(ctx, input, { ...options })

if (typeof image.getMeta === 'function') {
Expand All @@ -49,7 +49,7 @@ async function getMeta(ctx: ImageCTX, input: string, options?: ImageOptions) {
}
}

function resolveImage(ctx: ImageCTX, input: string, options: ImageOptions): ResolvedImage {
function resolveImage(ctx: ImageCTX, input: string, options: ImageOptions<any>): ResolvedImage {
if (input && typeof input !== 'string') {
throw new TypeError(`input must be a string (received ${typeof input}: ${JSON.stringify(input)})`)
}
Expand Down Expand Up @@ -124,9 +124,9 @@ function getPreset(ctx: ImageCTX, name?: string): ImageOptions {
return ctx.options.presets[name]
}

function getSizes(ctx: ImageCTX, input: string, opts: ImageSizesOptions): ImageSizes {
function getSizes(ctx: ImageCTX, input: string, opts?: ImageOptions<any>): ImageSizes {
// Merge preset options so preset-provided sizes/densities are respected
const preset = getPreset(ctx, opts.preset)
const preset = getPreset(ctx, opts?.preset)
const merged = defu(opts, preset)

const width = parseSize(merged.modifiers?.width)
Expand Down Expand Up @@ -160,7 +160,7 @@ function getSizes(ctx: ImageCTX, input: string, opts: ImageSizesOptions): ImageS
for (const density of densities) {
srcsetVariants.push({
width: variant._cWidth * density,
src: getVariantSrc(ctx, input, opts, variant, density),
src: getVariantSrc(ctx, input, variant, density, opts),
})
}
}
Expand All @@ -179,14 +179,14 @@ function getSizes(ctx: ImageCTX, input: string, opts: ImageSizesOptions): ImageS
variant = {
size: '',
screenMaxWidth: 0,
_cWidth: opts.modifiers?.width as number,
_cHeight: opts.modifiers?.height as number,
_cWidth: opts?.modifiers?.width as number,
_cHeight: opts?.modifiers?.height as number,
}
}

srcsetVariants.push({
width: density,
src: getVariantSrc(ctx, input, opts, variant, density),
src: getVariantSrc(ctx, input, variant, density, opts),
})
}
}
Expand Down Expand Up @@ -232,10 +232,10 @@ function getSizesVariant(key: string, size: string, height: number | undefined,
}
}

function getVariantSrc(ctx: ImageCTX, input: string, opts: ImageSizesOptions, variant: ImageSizesVariant, density: number) {
function getVariantSrc(ctx: ImageCTX, input: string, variant: ImageSizesVariant, density: number, opts?: ImageOptions) {
return ctx.$img!(input,
{
...opts.modifiers,
...opts?.modifiers,
width: variant._cWidth ? variant._cWidth * density : undefined,
height: variant._cHeight ? variant._cHeight * density : undefined,
},
Expand Down
26 changes: 14 additions & 12 deletions src/types/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ export interface ResolvedImageModifiers extends ImageModifiers {

type DefaultProvider = ProviderDefaults extends Record<'provider', unknown> ? ProviderDefaults['provider'] : never

export interface ImageOptions<Provider extends keyof ConfiguredImageProviders = DefaultProvider> {
provider?: Provider
type Sizes = Record<string, string | number> | string

export interface ImageOptions<TProvider extends keyof ConfiguredImageProviders = DefaultProvider> {
provider?: TProvider
preset?: string
densities?: string
modifiers?: Partial<Omit<ImageModifiers, 'format' | 'quality' | 'background' | 'fit'>>
& ('modifiers' extends keyof ConfiguredImageProviders[Provider] ? ConfiguredImageProviders[Provider]['modifiers'] : Record<string, unknown>)
sizes?: string | Record<string, any>
}

export interface ImageSizesOptions extends ImageOptions {
sizes: Record<string, string | number> | string
& ('modifiers' extends keyof ConfiguredImageProviders[TProvider] ? ConfiguredImageProviders[TProvider]['modifiers'] : Record<string, unknown>)
sizes?: Sizes
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this work in other contexts? e.g. if not passed to getSizes?

if it isn't respected then ImageSizesOptions should still be a separate type

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from what I can see, ImageSizesOptions was used solely for the purpose of getSizes

}

export type ProviderGetImage<T = Record<string, unknown>> = (src: string, options: Omit<ImageOptions, 'modifiers'> & { modifiers: Partial<ResolvedImageModifiers> } & T, ctx: ImageCTX) => ResolvedImage
Expand Down Expand Up @@ -84,11 +82,15 @@ export interface ImageSizes {
}

export interface Img {
(source: string, modifiers?: ImageOptions['modifiers'], options?: ImageOptions): ResolvedImage['url']
<TProvider extends keyof ConfiguredImageProviders>(
source: string,
modifiers?: ImageOptions<TProvider>['modifiers'],
options?: ImageOptions<TProvider>
): ResolvedImage['url']
options: CreateImageOptions
getImage: (source: string, options?: ImageOptions) => ResolvedImage
getSizes: (source: string, options?: ImageOptions, sizes?: string[]) => ImageSizes
getMeta: (source: string, options?: ImageOptions) => Promise<ImageInfo>
getImage: <TProvider extends keyof ConfiguredImageProviders>(source: string, options?: ImageOptions<TProvider>) => ResolvedImage
getSizes: <TProvider extends keyof ConfiguredImageProviders>(source: string, options?: ImageOptions<TProvider>) => ImageSizes
getMeta: <TProvider extends keyof ConfiguredImageProviders>(source: string, options?: ImageOptions<TProvider>) => Promise<ImageInfo>
}

export type $Img = Img & {
Expand Down
Loading