- JournalFeaturedImage renders <picture> from featured_images[].variants: a WebP source and the original format as srcset fallback, the original's width and height, alt; lazy in cards, eager with fetchpriority high on the post page; unchanged without variants - app/utils/srcset.ts (imageSrcsets) with node tests - acme fixtures and SSR expectations for both cases
38 lines
1.5 KiB
Vue
38 lines
1.5 KiB
Vue
<script setup lang="ts">
|
|
// A post's featured image. With the API's variants (D-85) it renders a
|
|
// <picture>: a WebP <source> and the <img> in the original format, both
|
|
// with srcset and sizes; without them, the single <img> as before. The
|
|
// intrinsic width/height reserve space before the image loads; the
|
|
// rendered size and crop come from --journal-image-ratio. eager is the
|
|
// post's main image: loaded at once, with fetchpriority high when the
|
|
// variants are there; cards load lazily.
|
|
import type { JournalFeaturedImage } from '../../utils/types.ts'
|
|
import { imageSrcsets } from '../../utils/srcset.ts'
|
|
|
|
const props = withDefaults(
|
|
defineProps<{ src: string | null | undefined; alt: string; eager?: boolean; image?: JournalFeaturedImage | null; sizes?: string }>(),
|
|
{ eager: false, image: null, sizes: '100vw' },
|
|
)
|
|
const sets = computed(() => (props.src ? imageSrcsets(props.image?.variants, props.src) : null))
|
|
</script>
|
|
|
|
<template>
|
|
<figure v-if="src" class="journal-featured-image">
|
|
<picture v-if="sets">
|
|
<source type="image/webp" :srcset="sets.webp" :sizes="sizes" />
|
|
<img
|
|
:src="src"
|
|
:srcset="sets.original"
|
|
:sizes="sizes"
|
|
:width="sets.width"
|
|
:height="sets.height"
|
|
:alt="alt"
|
|
:loading="eager ? 'eager' : 'lazy'"
|
|
:fetchpriority="eager ? 'high' : undefined"
|
|
decoding="async"
|
|
/>
|
|
</picture>
|
|
<img v-else :src="src" :alt="alt" width="1200" height="630" :loading="eager ? 'eager' : 'lazy'" decoding="async" />
|
|
</figure>
|
|
</template>
|