diff --git a/.nuxtrc b/.nuxtrc index 2ad658a79..a0351a8db 100644 --- a/.nuxtrc +++ b/.nuxtrc @@ -1,2 +1,3 @@ modules[]=@nuxt/test-utils/module modules[]=@nuxt/image +typescript.tsConfig.compilerOptions.noUncheckedIndexedAccess=true diff --git a/src/runtime/components/NuxtImg.vue b/src/runtime/components/NuxtImg.vue index 92b361da8..5ba4a44ed 100644 --- a/src/runtime/components/NuxtImg.vue +++ b/src/runtime/components/NuxtImg.vue @@ -138,7 +138,9 @@ onMounted(() => { if (placeholder.value) { const img = new Image() - img.src = mainSrc.value + if (mainSrc.value) { + img.src = mainSrc.value + } if (props.sizes) { img.sizes = sizes.value.sizes || '' diff --git a/src/runtime/components/NuxtPicture.vue b/src/runtime/components/NuxtPicture.vue index 0c17a94cd..888a310bc 100644 --- a/src/runtime/components/NuxtPicture.vue +++ b/src/runtime/components/NuxtPicture.vue @@ -61,7 +61,7 @@ const legacyFormat = computed(() => { return isTransparent.value ? 'png' : 'jpeg' }) -type Source = { src: string, srcset?: string, type?: string, sizes?: string } +type Source = { src?: string, srcset?: string, type?: string, sizes?: string } const sources = computed(() => { const formats = props.format?.split(',') || (originalFormat.value === 'svg' ? ['svg'] : ($img.options.format?.length ? [...$img.options.format] : ['webp'])) diff --git a/src/runtime/image.ts b/src/runtime/image.ts index 4f8172736..b7742ba58 100644 --- a/src/runtime/image.ts +++ b/src/runtime/image.ts @@ -75,7 +75,10 @@ function resolveImage(ctx: ImageCTX, input: string, options: ImageOptions): Reso if (!provider.supportsAlias) { for (const base in ctx.options.alias) { if (input.startsWith(base)) { - input = joinURL(ctx.options.alias[base], input.substr(base.length)) + const alias = ctx.options.alias[base] + if (alias) { + input = joinURL(alias, input.slice(base.length)) + } } } } @@ -168,7 +171,8 @@ function getSizes(ctx: ImageCTX, input: string, opts: ImageSizesOptions): ImageS // 'densities path' for (const density of densities) { const key = Object.keys(sizes)[0] - let variant = getSizesVariant(key, String(sizes[key]), height, hwRatio, ctx) + + let variant = key ? getSizesVariant(key, String(sizes[key]), height, hwRatio, ctx) : undefined // unable to resolve variant, fallback to default modifiers if (variant === undefined) { diff --git a/src/runtime/providers/awsAmplify.ts b/src/runtime/providers/awsAmplify.ts index 4905d7389..eb5f668c5 100644 --- a/src/runtime/providers/awsAmplify.ts +++ b/src/runtime/providers/awsAmplify.ts @@ -3,7 +3,7 @@ import type { ProviderGetImage } from '../../module' export const getImage: ProviderGetImage = (src, { modifiers, baseURL = '/_amplify/image' } = {}, ctx) => { const validWidths = Object.values(ctx.options.screens || {}).sort((a, b) => a - b) - const largestWidth = validWidths[validWidths.length - 1] + const largestWidth = validWidths[validWidths.length - 1] || 0 let width = Number(modifiers?.width || 0) if (!width) { diff --git a/src/runtime/providers/hygraph.ts b/src/runtime/providers/hygraph.ts index fc1816a30..8d50e376f 100644 --- a/src/runtime/providers/hygraph.ts +++ b/src/runtime/providers/hygraph.ts @@ -28,6 +28,7 @@ export function splitUpURL(url: string, baseURL: string) { // get baseId // -> cltsj3mii0pvd07vwb5cyh1ig + // @ts-expect-error fixing in separate PR const baseId = bothIds.split('/')[0] // get imageId @@ -61,6 +62,7 @@ export function optimizeHygraphImage(baseURL: string, url: string, optimizations } const optim = `${optimBase}=${optimList.join(',')}` + // @ts-expect-error fixing in separate PR const result = joinURL(baseURL, baseId, optim, quality, imageFormat, imageId) return result diff --git a/src/runtime/providers/vercel.ts b/src/runtime/providers/vercel.ts index e406bb0d9..dc0feb7aa 100644 --- a/src/runtime/providers/vercel.ts +++ b/src/runtime/providers/vercel.ts @@ -5,7 +5,7 @@ import type { ProviderGetImage } from '../../module' export const getImage: ProviderGetImage = (src, { modifiers, baseURL = '/_vercel/image' } = {}, ctx) => { const validWidths = Object.values(ctx.options.screens || {}).sort((a, b) => a - b) - const largestWidth = validWidths[validWidths.length - 1] + const largestWidth = validWidths[validWidths.length - 1] || 0 let width = Number(modifiers?.width || 0) if (!width) { diff --git a/src/runtime/utils/index.ts b/src/runtime/utils/index.ts index bcb58377f..b7a33510c 100644 --- a/src/runtime/utils/index.ts +++ b/src/runtime/utils/index.ts @@ -49,7 +49,7 @@ export function createOperationsGenerator({ formatter, keyMap, joinWith = '/', v .map(([key, value]) => { const mapper = map[key] if (typeof mapper === 'function') { - value = mapper(modifiers[key]) + value = mapper(modifiers[key]!) } key = typeof keyMap === 'function' ? keyMap(key) : key @@ -128,10 +128,10 @@ export function parseSizes(input: Record | string): Rec for (const entry of input.split(/[\s,]+/).filter(e => e)) { const s = entry.split(':') if (s.length !== 2) { - sizes['1px'] = s[0].trim() + sizes['1px'] = s[0]!.trim() } else { - sizes[s[0].trim()] = s[1].trim() + sizes[s[0]!.trim()] = s[1]!.trim() } } } diff --git a/src/runtime/utils/prerender.ts b/src/runtime/utils/prerender.ts index 954acd349..dfc018c1a 100644 --- a/src/runtime/utils/prerender.ts +++ b/src/runtime/utils/prerender.ts @@ -8,16 +8,12 @@ export function prerenderStaticImages(src = '', srcset = '') { const paths = [ src, - ...srcset.split(', ').map(s => s.trim().split(' ')[0].trim()), + ...srcset.split(', ').map(s => s.trim().split(' ')[0]!.trim()), ].filter(s => s && s.includes('/_ipx/')) if (!paths.length) { return } - appendHeader( - useRequestEvent()!, - 'x-nitro-prerender', - paths.map(p => encodeURIComponent(p)).join(', '), - ) + appendHeader(useRequestEvent()!, 'x-nitro-prerender', paths.map(p => encodeURIComponent(p)).join(', ')) } diff --git a/src/types/image.ts b/src/types/image.ts index 542f6b5d9..04ab7df39 100644 --- a/src/types/image.ts +++ b/src/types/image.ts @@ -62,7 +62,7 @@ export interface ResolvedImage { export interface ImageSizes { srcset: string sizes: string | undefined - src: string + src?: string } export interface Img { diff --git a/test/unit/image.test.ts b/test/unit/image.test.ts index 1147c77e7..5949a6f8c 100644 --- a/test/unit/image.test.ts +++ b/test/unit/image.test.ts @@ -215,7 +215,7 @@ describe('Renders placeholder image', () => { domSrc = wrapper.find('img').element.getAttribute('src') expect(domSrc).toMatchInlineSnapshot('"/_ipx/s_200x200/image.png"') - expect(wrapper.emitted().load[0]).toStrictEqual([loadEvent]) + expect(wrapper.emitted().load![0]).toStrictEqual([loadEvent]) }) it('props.placeholder with sizes', async () => { @@ -246,7 +246,7 @@ describe('Renders placeholder image', () => { sizes = wrapper.find('img').element.getAttribute('sizes') expect(sizes).toMatchInlineSnapshot('"(max-width: 500px) 200px, (max-width: 900px) 500px, 900px"') - expect(wrapper.emitted().load[0]).toStrictEqual([loadEvent]) + expect(wrapper.emitted().load![0]).toStrictEqual([loadEvent]) }) it('placeholder class can be set', async () => { diff --git a/test/unit/picture.test.ts b/test/unit/picture.test.ts index ed1690fd0..e5c2357c5 100644 --- a/test/unit/picture.test.ts +++ b/test/unit/picture.test.ts @@ -60,7 +60,7 @@ describe('Renders simple image', () => { it('props.src is picked up by getImage()', () => { [['source', 'srcset', '/_ipx/f_webp&s_500x500/image.png'], ['img', 'src']].forEach(([element, attribute, customSrc]) => { - const domSrc = wrapper.find(element).element.getAttribute(attribute) + const domSrc = wrapper.find(element!).element.getAttribute(attribute!) expect(domSrc).toContain(customSrc || src) }) }) @@ -117,7 +117,7 @@ describe('Renders simple image', () => { await nextTick() ;[['source', 'srcset', '/_ipx/f_webp&s_500x500/image.jpeg'], ['img', 'src']].forEach(([element, attribute, src]) => { - const domSrc = wrapper.find(element).element.getAttribute(attribute) + const domSrc = wrapper.find(element!).element.getAttribute(attribute!) expect(domSrc).toContain(src || newSource) }) })