Skip to content

Commit

Permalink
Refactor Props of Image and Picture component to support type c…
Browse files Browse the repository at this point in the history
…hecking (#5788)

* correct props type

* refactor Picture and Image typings

* add missing `alt` property

* add changeset

* apply suggestions

* correct `astro/types` import

Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com>

* apply suggestions

* convert to type import

Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com>
  • Loading branch information
MoustaphaDev and Princesseuh committed Jan 18, 2023
1 parent 28556a8 commit 006405d
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 59 deletions.
6 changes: 6 additions & 0 deletions .changeset/mean-suits-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@astrojs/image': patch
---

- Refactor types to support props auto-completion for the `Image` and `Picture` components.
- Pass previously missing `alt` prop to the `getPicture` function
24 changes: 3 additions & 21 deletions packages/integrations/image/components/Image.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,11 @@
// @ts-ignore
import { getImage } from '../dist/index.js';
import { warnForMissingAlt } from './index.js';
import type { ImgHTMLAttributes } from './index.js';
import type { ImageMetadata, TransformOptions, OutputFormat } from '../dist/index.js';
import type { ImageComponentLocalImageProps, ImageComponentRemoteImageProps } from './index.js';
interface LocalImageProps
extends Omit<TransformOptions, 'src'>,
Omit<ImgHTMLAttributes, 'src' | 'width' | 'height'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
}
interface RemoteImageProps extends TransformOptions, astroHTML.JSX.ImgHTMLAttributes {
src: string;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
format?: OutputFormat;
width: number;
height: number;
}
export type Props = LocalImageProps | RemoteImageProps;
export type Props = ImageComponentLocalImageProps | ImageComponentRemoteImageProps;
const { loading = 'lazy', decoding = 'async', ...props } = Astro.props as Props;
const { loading = 'lazy', decoding = 'async', ...props } = Astro.props;
if (props.alt === undefined || props.alt === null) {
warnForMissingAlt();
Expand Down
34 changes: 4 additions & 30 deletions packages/integrations/image/components/Picture.astro
Original file line number Diff line number Diff line change
@@ -1,36 +1,9 @@
---
import { getPicture } from '../dist/index.js';
import { warnForMissingAlt } from './index.js';
import type { ImgHTMLAttributes, HTMLAttributes } from './index.js';
import type { ImageMetadata, OutputFormat, TransformOptions } from '../dist/index.js';
import type { PictureComponentLocalImageProps, PictureComponentRemoteImageProps } from './index.js';
interface LocalImageProps
extends Omit<HTMLAttributes, 'src' | 'width' | 'height'>,
Omit<TransformOptions, 'src'>,
Pick<astroHTML.JSX.ImgHTMLAttributes, 'loading' | 'decoding'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
sizes: HTMLImageElement['sizes'];
widths: number[];
formats?: OutputFormat[];
}
interface RemoteImageProps
extends Omit<HTMLAttributes, 'src' | 'width' | 'height'>,
TransformOptions,
Pick<ImgHTMLAttributes, 'loading' | 'decoding'> {
src: string;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
sizes: HTMLImageElement['sizes'];
widths: number[];
aspectRatio: TransformOptions['aspectRatio'];
formats?: OutputFormat[];
background: TransformOptions['background'];
}
export type Props = LocalImageProps | RemoteImageProps;
export type Props = PictureComponentLocalImageProps | PictureComponentRemoteImageProps;
const {
src,
Expand All @@ -45,7 +18,7 @@ const {
loading = 'lazy',
decoding = 'async',
...attrs
} = Astro.props as Props;
} = Astro.props;
if (alt === undefined || alt === null) {
warnForMissingAlt();
Expand All @@ -59,6 +32,7 @@ const { image, sources } = await getPicture({
fit,
background,
position,
alt,
});
delete image.width;
Expand Down
59 changes: 52 additions & 7 deletions packages/integrations/image/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,60 @@
/// <reference types="astro/astro-jsx" />
export { default as Image } from './Image.astro';
export { default as Picture } from './Picture.astro';
import type { HTMLAttributes } from 'astro/types';

// TODO: should these directives be removed from astroHTML.JSX?
export type ImgHTMLAttributes = Omit<
astroHTML.JSX.ImgHTMLAttributes,
'client:list' | 'set:text' | 'set:html' | 'is:raw'
>;
export type HTMLAttributes = Omit<
import type { TransformOptions, OutputFormat } from '../dist/loaders/index.js';
import type { ImageMetadata } from '../dist/vite-plugin-astro-image.js';
import type { AstroBuiltinAttributes } from 'astro';

export interface ImageComponentLocalImageProps
extends Omit<TransformOptions, 'src'>,
Omit<ImgHTMLAttributes, 'src' | 'width' | 'height'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
}

export interface ImageComponentRemoteImageProps extends TransformOptions, ImgHTMLAttributes {
src: string;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
format?: OutputFormat;
width: number;
height: number;
}

export interface PictureComponentLocalImageProps
extends GlobalHTMLAttributes,
Omit<TransformOptions, 'src'>,
Pick<ImgHTMLAttributes, 'loading' | 'decoding'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
sizes: HTMLImageElement['sizes'];
widths: number[];
formats?: OutputFormat[];
}

export interface PictureComponentRemoteImageProps
extends GlobalHTMLAttributes,
TransformOptions,
Pick<ImgHTMLAttributes, 'loading' | 'decoding'> {
src: string;
/** Defines an alternative text description of the image. Set to an empty string (alt="") if the image is not a key part of the content (it's decoration or a tracking pixel). */
alt: string;
sizes: HTMLImageElement['sizes'];
widths: number[];
aspectRatio: TransformOptions['aspectRatio'];
formats?: OutputFormat[];
background: TransformOptions['background'];
}

export type ImgHTMLAttributes = HTMLAttributes<'img'>;

export type GlobalHTMLAttributes = Omit<
astroHTML.JSX.HTMLAttributes,
'client:list' | 'set:text' | 'set:html' | 'is:raw'
keyof Omit<AstroBuiltinAttributes, 'class:list'>
>;

let altWarningShown = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const publicImage = new URL('./hero.jpg', Astro.url);
<!-- Head Stuff -->
</head>
<body>
<Image id="hero" src={publicImage.pathname} width={768} height={414} format="webp" alt="hero" />
<Image id="hero" src={publicImage.pathname} width={768} height={414} format="webp" alt="hero" />
<br />
<Image id="spaces" src={introJpg} width={768} height={414} format="webp" alt="spaces" />
<br />
Expand Down

0 comments on commit 006405d

Please sign in to comment.