Skip to content

Commit

Permalink
adds support for string width/height on <Image />
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony Sullivan committed Aug 29, 2022
1 parent c1ba2e9 commit 279be90
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 15 deletions.
5 changes: 2 additions & 3 deletions .changeset/lucky-mirrors-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

`<Image />` and `<Picture />` now support using images in the `/public` directory :tada:

- Updates `<Image />` to support strings for `width` and `height` to match `<img>`'s HTML syntax
- Moving handling of local image files into the Vite plugin
- Optimized image files are now built to `/dist` with hashes provided by Vite, removing the need for a `/dist/_image` directory
- Removes three npm dependencies: `etag`, `slash`, and `tiny-glob`
- Replaces `mrmime` with the `mime` package already used by Astro's SSR server
- Simplifies the injected `_image` route to work for both `dev` and `build`
- Simplifies the injected `_image` route used for optimizing images on-demand
- Adds a new test suite for using images with `@astrojs/mdx` - including optimizing images straight from `/public`
2 changes: 0 additions & 2 deletions packages/integrations/image/components/Image.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ interface LocalImageProps
interface RemoteImageProps extends TransformOptions, astroHTML.JSX.ImgHTMLAttributes {
src: string;
format: OutputFormat;
width: number;
height: number;
}
export type Props = LocalImageProps | RemoteImageProps;
Expand Down
36 changes: 30 additions & 6 deletions packages/integrations/image/src/lib/get-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@ export interface GetImageTransform extends Omit<TransformOptions, 'src'> {
src: string | ImageMetadata | Promise<{ default: ImageMetadata }>;
}

function parseDimension(value: number | string | undefined, name: string, required = false) {
if (typeof value === 'number') {
return value;
}

try {
// @ts-ignore
return parseInt(value);
} catch {
if (required) {
throw new Error(`"${name}" must be a number or string, received "${value}" (${typeof value})`);
}
}

return undefined;
}

function resolveSize(transform: TransformOptions): TransformOptions {
// keep width & height as provided
if (transform.width && transform.height) {
return transform;
}

if (!transform.width && !transform.height) {
const width = parseDimension(transform.width, 'width', true);
const height = parseDimension(transform.height, 'height', true);

if (!width && !height) {
throw new Error(`"width" and "height" cannot both be undefined`);
}

Expand All @@ -39,15 +59,15 @@ function resolveSize(transform: TransformOptions): TransformOptions {
// only width was provided, calculate height
return {
...transform,
width: transform.width,
height: Math.round(transform.width / aspectRatio),
width,
height: Math.round(width! / aspectRatio),
} as TransformOptions;
} else if (transform.height) {
// only height was provided, calculate width
return {
...transform,
width: Math.round(transform.height * aspectRatio),
height: transform.height,
width: Math.round(height! * aspectRatio),
height,
};
}

Expand All @@ -63,7 +83,11 @@ async function resolveTransform(input: GetImageTransform): Promise<TransformOpti
// resolve the metadata promise, usually when the ESM import is inlined
const metadata = 'then' in input.src ? (await input.src).default : input.src;

let { width, height, aspectRatio, format = metadata.format, ...rest } = input;
let { aspectRatio, format = metadata.format, ...rest } = input;

// width and height are optional here since metadata is available
let width = parseDimension(input.width, 'width', false);
let height = parseDimension(input.height, 'height', false);

if (!width && !height) {
// neither dimension was provided, use the file metadata
Expand Down
4 changes: 2 additions & 2 deletions packages/integrations/image/src/loaders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ export interface TransformOptions {
* The desired width of the output image. Combine with `height` to crop the image
* to an exact size, or `aspectRatio` to automatically calculate and crop the height.
*/
width?: number;
width?: number | string;
/**
* The desired height of the output image. Combine with `height` to crop the image
* to an exact size, or `aspectRatio` to automatically calculate and crop the width.
*/
height?: number;
height?: number | string;
/**
* The desired aspect ratio of the output image. Combine with either `width` or `height`
* to automatically calculate and crop the other dimension.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Image } from '@astrojs/image/components';
<body>
<Image id="hero" src="/hero.jpg" width={768} height={414} format="webp" />
<br />
<Image id="social-jpg" src={socialJpg} width={506} height={253} />
<Image id="social-jpg" src={socialJpg} width="506" height="253" />
<br />
<Image id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width={544} height={184} format="webp" />
<br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Image } from '@astrojs/image/components';

<Image id="hero" src="/hero.jpg" width={768} height={414} format="webp" />
<br />
<Image id="social-jpg" src={socialJpg} width={506} height={253} />
<Image id="social-jpg" src={socialJpg} width="506" height="253" />
<br />
<Image id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width={544} height={184} format="webp" />
<br />
Expand Down

0 comments on commit 279be90

Please sign in to comment.