diff options
author | 2022-07-08 21:37:55 +0000 | |
---|---|---|
committer | 2022-07-08 21:37:55 +0000 | |
commit | 89d76753a0dc50b2967d1fa9d36e34bde2722b83 (patch) | |
tree | cfaf7ecf53999c15bb56646dad8c57e013c68450 /packages/integrations/image/components/Image.astro | |
parent | ec392589f6d60785e45a49acdb3b9bda29c566df (diff) | |
download | astro-89d76753a0dc50b2967d1fa9d36e34bde2722b83.tar.gz astro-89d76753a0dc50b2967d1fa9d36e34bde2722b83.tar.zst astro-89d76753a0dc50b2967d1fa9d36e34bde2722b83.zip |
Adds a new `<Picture>` component to the image integration (#3866)
* moving all normalization logic out of the Image component
* refactor: only require loaders to provide the image src
* Adding a `<Picture />` component
* fixing types.ts imports
* refactor: moving getImage to it's own file
* updating component types to use astroHTML.JSX
* Revert "updating component types to use astroHTML.JSX"
This reverts commit 6e5f578da8d1d3fd262f3cd9add7549f7580af97.
* going back to letting loaders add extra HTML attributes
* Always use lazy loading and async decoding
* Cleaning up the Picture component
* Adding test coverage for <Picture>
* updating the README
* using JSX types for the Image and Picture elements
* chore: adding changeset
* Update packages/integrations/image/src/get-image.ts
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
* allow users to override loading and async on the <img>
* renaming config to constants, exporting getPicture()
* found the right syntax to import astro-jsx
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Diffstat (limited to 'packages/integrations/image/components/Image.astro')
-rw-r--r-- | packages/integrations/image/components/Image.astro | 112 |
1 files changed, 9 insertions, 103 deletions
diff --git a/packages/integrations/image/components/Image.astro b/packages/integrations/image/components/Image.astro index 51d4182a2..326c1bc6c 100644 --- a/packages/integrations/image/components/Image.astro +++ b/packages/integrations/image/components/Image.astro @@ -4,7 +4,7 @@ import loader from 'virtual:image-loader'; import { getImage } from '../src/index.js'; import type { ImageAttributes, ImageMetadata, TransformOptions, OutputFormat } from '../src/types.js'; -export interface LocalImageProps extends Omit<TransformOptions, 'src'>, Omit<ImageAttributes, 'src'> { +export interface LocalImageProps extends Omit<TransformOptions, 'src'>, Omit<ImageAttributes, 'src' | 'width' | 'height'> { src: ImageMetadata | Promise<{ default: ImageMetadata }>; } @@ -17,109 +17,15 @@ export interface RemoteImageProps extends TransformOptions, ImageAttributes { export type Props = LocalImageProps | RemoteImageProps; -function isLocalImage(props: Props): props is LocalImageProps { - // vite-plugin-astro-image resolves ESM imported images - // to a metadata object - return typeof props.src !== 'string'; -} - -function parseAspectRatio(aspectRatio: TransformOptions['aspectRatio']) { - if (!aspectRatio) { - return undefined; - } - - // parse aspect ratio strings, if required (ex: "16:9") - if (typeof aspectRatio === 'number') { - aspectRatio = aspectRatio; - } else { - const [width, height] = aspectRatio.split(':'); - aspectRatio = parseInt(width) / parseInt(height); - } -} - -async function resolveProps(props: Props): Promise<TransformOptions> { - // For remote images, just check the width/height provided - if (!isLocalImage(props)) { - return calculateSize(props); - } +const { loading = "lazy", decoding = "async", ...props } = Astro.props as Props; - let { width, height, aspectRatio, format, ...rest } = props; - - // if a Promise<ImageMetadata> was provided, unwrap it first - const { src, ...metadata } = 'then' in props.src ? (await props.src).default : props.src; - - if (!width && !height) { - // neither dimension was provided, use the file metadata - width = metadata.width; - height = metadata.height; - } else if (width) { - // one dimension was provided, calculate the other - let ratio = parseAspectRatio(aspectRatio) || metadata.width / metadata.height; - height = height || width / ratio; - } else if (height) { - // one dimension was provided, calculate the other - let ratio = parseAspectRatio(aspectRatio) || metadata.width / metadata.height; - width = width || height * ratio; - } - - return { - ...rest, - width, - height, - aspectRatio, - src, - format: format || metadata.format as OutputFormat, - } -} - -function calculateSize(transform: TransformOptions): TransformOptions { - // keep width & height as provided - if (transform.width && transform.height) { - return transform; - } - - if (!transform.width && !transform.height) { - throw new Error(`"width" and "height" cannot both be undefined`); - } - - if (!transform.aspectRatio) { - throw new Error(`"aspectRatio" must be included if only "${transform.width ? "width": "height"}" is provided`) - } - - let aspectRatio: number; +const attrs = await getImage(loader, props); +--- - // parse aspect ratio strings, if required (ex: "16:9") - if (typeof transform.aspectRatio === 'number') { - aspectRatio = transform.aspectRatio; - } else { - const [width, height] = transform.aspectRatio.split(':'); - aspectRatio = parseInt(width) / parseInt(height); - } +<img {...attrs} {loading} {decoding} /> - if (transform.width) { - // only width was provided, calculate height - return { - ...transform, - width: transform.width, - height: transform.width / aspectRatio - }; - } else if (transform.height) { - // only height was provided, calculate width - return { - ...transform, - width: transform.height * aspectRatio, - height: transform.height - } +<style> + img { + content-visibility: auto; } - - return transform; -} - -const props = Astro.props as Props; - -const imageProps = await resolveProps(props); - -const attrs = await getImage(loader, imageProps); ---- - -<img {...attrs} /> +</style> |