summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/fifty-apricots-clap.md5
-rw-r--r--.changeset/five-singers-notice.md5
-rw-r--r--packages/astro/client-base.d.ts173
-rw-r--r--packages/astro/client.d.ts174
-rw-r--r--packages/astro/package.json2
-rw-r--r--packages/integrations/image/README.md224
-rw-r--r--packages/integrations/image/client.d.ts55
-rw-r--r--packages/integrations/image/components/Image.astro9
-rw-r--r--packages/integrations/image/components/Picture.astro13
-rw-r--r--packages/integrations/image/components/index.ts5
-rw-r--r--packages/integrations/image/package.json13
-rw-r--r--packages/integrations/image/src/build/ssg.ts2
-rw-r--r--packages/integrations/image/src/index.ts119
-rw-r--r--packages/integrations/image/src/integration.ts93
-rw-r--r--packages/integrations/image/src/lib/get-image.ts8
-rw-r--r--packages/integrations/image/src/lib/get-picture.ts6
-rw-r--r--packages/integrations/image/src/loaders/index.ts (renamed from packages/integrations/image/src/types.ts)44
-rw-r--r--packages/integrations/image/src/loaders/sharp.ts2
-rw-r--r--packages/integrations/image/src/utils/images.ts2
-rw-r--r--packages/integrations/image/src/utils/metadata.ts3
-rw-r--r--packages/integrations/image/src/utils/paths.ts2
-rw-r--r--packages/integrations/image/src/vite-plugin-astro-image.ts10
22 files changed, 606 insertions, 363 deletions
diff --git a/.changeset/fifty-apricots-clap.md b/.changeset/fifty-apricots-clap.md
new file mode 100644
index 000000000..2fcf04fe7
--- /dev/null
+++ b/.changeset/fifty-apricots-clap.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Adding support for custom "astro/client" type definitions in `@astrojs/image`
diff --git a/.changeset/five-singers-notice.md b/.changeset/five-singers-notice.md
new file mode 100644
index 000000000..2e1a930ee
--- /dev/null
+++ b/.changeset/five-singers-notice.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/image': minor
+---
+
+Big improvements to the TypeScript and Language Tools support for `@astrojs/image` :tada:
diff --git a/packages/astro/client-base.d.ts b/packages/astro/client-base.d.ts
new file mode 100644
index 000000000..1e65d7f71
--- /dev/null
+++ b/packages/astro/client-base.d.ts
@@ -0,0 +1,173 @@
+/// <reference types="vite/types/importMeta" />
+
+// CSS modules
+type CSSModuleClasses = { readonly [key: string]: string };
+
+declare module '*.module.css' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.scss' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.sass' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.less' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.styl' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.stylus' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+declare module '*.module.pcss' {
+ const classes: CSSModuleClasses;
+ export default classes;
+}
+
+// CSS
+declare module '*.css' {
+ const css: string;
+ export default css;
+}
+declare module '*.scss' {
+ const css: string;
+ export default css;
+}
+declare module '*.sass' {
+ const css: string;
+ export default css;
+}
+declare module '*.less' {
+ const css: string;
+ export default css;
+}
+declare module '*.styl' {
+ const css: string;
+ export default css;
+}
+declare module '*.stylus' {
+ const css: string;
+ export default css;
+}
+declare module '*.pcss' {
+ const css: string;
+ export default css;
+}
+
+// Built-in asset types
+// see `src/constants.ts`
+
+// media
+declare module '*.mp4' {
+ const src: string;
+ export default src;
+}
+declare module '*.webm' {
+ const src: string;
+ export default src;
+}
+declare module '*.ogg' {
+ const src: string;
+ export default src;
+}
+declare module '*.mp3' {
+ const src: string;
+ export default src;
+}
+declare module '*.wav' {
+ const src: string;
+ export default src;
+}
+declare module '*.flac' {
+ const src: string;
+ export default src;
+}
+declare module '*.aac' {
+ const src: string;
+ export default src;
+}
+
+// fonts
+declare module '*.woff' {
+ const src: string;
+ export default src;
+}
+declare module '*.woff2' {
+ const src: string;
+ export default src;
+}
+declare module '*.eot' {
+ const src: string;
+ export default src;
+}
+declare module '*.ttf' {
+ const src: string;
+ export default src;
+}
+declare module '*.otf' {
+ const src: string;
+ export default src;
+}
+
+// other
+declare module '*.wasm' {
+ const initWasm: (options: WebAssembly.Imports) => Promise<WebAssembly.Exports>;
+ export default initWasm;
+}
+declare module '*.webmanifest' {
+ const src: string;
+ export default src;
+}
+declare module '*.pdf' {
+ const src: string;
+ export default src;
+}
+declare module '*.txt' {
+ const src: string;
+ export default src;
+}
+
+// web worker
+declare module '*?worker' {
+ const workerConstructor: {
+ new (): Worker;
+ };
+ export default workerConstructor;
+}
+
+declare module '*?worker&inline' {
+ const workerConstructor: {
+ new (): Worker;
+ };
+ export default workerConstructor;
+}
+
+declare module '*?sharedworker' {
+ const sharedWorkerConstructor: {
+ new (): SharedWorker;
+ };
+ export default sharedWorkerConstructor;
+}
+
+declare module '*?raw' {
+ const src: string;
+ export default src;
+}
+
+declare module '*?url' {
+ const src: string;
+ export default src;
+}
+
+declare module '*?inline' {
+ const src: string;
+ export default src;
+}
diff --git a/packages/astro/client.d.ts b/packages/astro/client.d.ts
index cfbb65ef0..44da8654b 100644
--- a/packages/astro/client.d.ts
+++ b/packages/astro/client.d.ts
@@ -1,69 +1,4 @@
-/// <reference types="vite/types/importMeta" />
-
-// CSS modules
-type CSSModuleClasses = { readonly [key: string]: string };
-
-declare module '*.module.css' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.scss' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.sass' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.less' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.styl' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.stylus' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-declare module '*.module.pcss' {
- const classes: CSSModuleClasses;
- export default classes;
-}
-
-// CSS
-declare module '*.css' {
- const css: string;
- export default css;
-}
-declare module '*.scss' {
- const css: string;
- export default css;
-}
-declare module '*.sass' {
- const css: string;
- export default css;
-}
-declare module '*.less' {
- const css: string;
- export default css;
-}
-declare module '*.styl' {
- const css: string;
- export default css;
-}
-declare module '*.stylus' {
- const css: string;
- export default css;
-}
-declare module '*.pcss' {
- const css: string;
- export default css;
-}
-
-// Built-in asset types
-// see `src/constants.ts`
+/// <reference path="./client-base.d.ts" />
// images
declare module '*.jpg' {
@@ -98,110 +33,3 @@ declare module '*.avif' {
const src: string;
export default src;
}
-
-// media
-declare module '*.mp4' {
- const src: string;
- export default src;
-}
-declare module '*.webm' {
- const src: string;
- export default src;
-}
-declare module '*.ogg' {
- const src: string;
- export default src;
-}
-declare module '*.mp3' {
- const src: string;
- export default src;
-}
-declare module '*.wav' {
- const src: string;
- export default src;
-}
-declare module '*.flac' {
- const src: string;
- export default src;
-}
-declare module '*.aac' {
- const src: string;
- export default src;
-}
-
-// fonts
-declare module '*.woff' {
- const src: string;
- export default src;
-}
-declare module '*.woff2' {
- const src: string;
- export default src;
-}
-declare module '*.eot' {
- const src: string;
- export default src;
-}
-declare module '*.ttf' {
- const src: string;
- export default src;
-}
-declare module '*.otf' {
- const src: string;
- export default src;
-}
-
-// other
-declare module '*.wasm' {
- const initWasm: (options: WebAssembly.Imports) => Promise<WebAssembly.Exports>;
- export default initWasm;
-}
-declare module '*.webmanifest' {
- const src: string;
- export default src;
-}
-declare module '*.pdf' {
- const src: string;
- export default src;
-}
-declare module '*.txt' {
- const src: string;
- export default src;
-}
-
-// web worker
-declare module '*?worker' {
- const workerConstructor: {
- new (): Worker;
- };
- export default workerConstructor;
-}
-
-declare module '*?worker&inline' {
- const workerConstructor: {
- new (): Worker;
- };
- export default workerConstructor;
-}
-
-declare module '*?sharedworker' {
- const sharedWorkerConstructor: {
- new (): SharedWorker;
- };
- export default sharedWorkerConstructor;
-}
-
-declare module '*?raw' {
- const src: string;
- export default src;
-}
-
-declare module '*?url' {
- const src: string;
- export default src;
-}
-
-declare module '*?inline' {
- const src: string;
- export default src;
-}
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 8b56e1500..19943f0c5 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -27,6 +27,7 @@
".": "./astro.js",
"./env": "./env.d.ts",
"./client": "./client.d.ts",
+ "./client-base": "./client-base.d.ts",
"./astro-jsx": "./astro-jsx.d.ts",
"./jsx/*": "./dist/jsx/*",
"./jsx-runtime": "./dist/jsx-runtime/index.js",
@@ -65,6 +66,7 @@
"config.mjs",
"env.d.ts",
"client.d.ts",
+ "client-base.d.ts",
"astro-jsx.d.ts",
"README.md",
"vendor"
diff --git a/packages/integrations/image/README.md b/packages/integrations/image/README.md
index c24a84e17..a5a4438c1 100644
--- a/packages/integrations/image/README.md
+++ b/packages/integrations/image/README.md
@@ -63,11 +63,205 @@ export default {
Then, restart the dev server.
</details>
+### Update `tsconfig.json`
+
+For the best development experience, add the integrations type definitions to your project's `tsconfig.json` file.
+
+```json
+{
+ "compilerOptions": {
+ // Replace `astro/client` with `@astrojs/image/client`
+ "types": ["@astrojs/image/client"]
+ }
+}
+```
+
## Usage
+The included `sharp` transformer supports resizing images and encoding them to different image formats. Third-party image services will be able to add support for custom transformations as well (ex: `blur`, `filter`, `rotate`, etc).
+
+### `<Image />`
+
The built-in `<Image />` component is used to create an optimized `<img />` for both remote images hosted on other domains as well as local images imported from your project's `src` directory.
-The included `sharp` transformer supports resizing images and encoding them to different image formats. Third-party image services will be able to add support for custom transformations as well (ex: `blur`, `filter`, `rotate`, etc).
+In addition to the component-specific properties, any valid HTML attribute for the `<img />` included in the `<Image />` component will be included in the built `<img />`.
+
+#### src
+
+<p>
+
+**Type:** `string` | `ImageMetadata` | `Promise<ImageMetadata>`<br>
+**Required:** `true`
+</p>
+
+Source for the original image file.
+
+For images in your project's repository, use the `src` relative to the `public` directory. For remote images, provide the full URL.
+
+#### format
+
+<p>
+
+**Type:** 'avif' | 'jpeg' | 'png' | 'webp'<br>
+**Default:** `undefined`
+</p>
+
+The output format to be used in the optimized image. The original image format will be used if `format` is not provided.
+
+#### quality
+
+<p>
+
+**Type:** `number`<br>
+**Default:** `undefined`
+</p>
+
+The compression quality used during optimization. The image service will use a default quality if not provided.
+
+#### width
+
+<p>
+
+**Type:** `number`<br>
+**Default:** `undefined`
+</p>
+
+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.
+
+Dimensions are optional for local images, the original image size will be used if not provided.
+
+For remote images, the integration needs to be able to calculate dimensions for the optimized image. This can be done by providing `width` and `height` or by providing one dimension and an `aspectRatio`.
+
+#### height
+
+<p>
+
+**Type:** `number`<br>
+**Default:** `undefined`
+</p>
+
+The desired height of the output image. Combine with `width` to crop the image to an exact size, or `aspectRatio` to automatically calculate and crop the width.
+
+Dimensions are optional for local images, the original image size will be used if not provided.
+
+For remote images, the integration needs to be able to calculate dimensions for the optimized image. This can be done by providing `width` and `height` or by providing one dimension and an `aspectRatio`.
+
+#### aspectRatio
+
+<p>
+
+**Type:** `number` | `string`<br>
+**Default:** `undefined`
+</p>
+
+The desired aspect ratio of the output image. Combine with either `width` or `height` to automatically calculate and crop the other dimension.
+
+A `string` can be provided in the form of `{width}:{height}`, ex: `16:9` or `3:4`.
+
+A `number` can also be provided, useful when the aspect ratio is calculated at build time. This can be an inline number such as `1.777` or inlined as a JSX expression like `aspectRatio={16/9}`.
+
+### `<Picture /`>
+
+#### src
+
+<p>
+
+**Type:** `string` | `ImageMetadata` | `Promise<ImageMetadata>`<br>
+**Required:** `true`
+</p>
+
+Source for the original image file.
+
+For images in your project's repository, use the `src` relative to the `public` directory. For remote images, provide the full URL.
+
+#### alt
+
+<p>
+
+**Type:** `string`<br>
+**Default:** `undefined`
+</p>
+
+If provided, the `alt` string will be included on the built `<img />` element.
+
+#### sizes
+
+<p>
+
+**Type:** `string`<br>
+**Required:** `true`
+</p>
+
+The HTMLImageElement property `sizes` allows you to specify the layout width of the image for each of a list of media conditions.
+
+See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes) for more details.
+
+#### widths
+
+<p>
+
+**Type:** `number[]`<br>
+**Reuqired:** `true`
+</p>
+
+The list of sizes that should be built for responsive images. This is combined with `aspectRatio` to calculate the final dimensions of each built image.
+
+```astro
+// Builds three images: 400x400, 800x800, and 1200x1200
+<Picture src={...} widths={[400, 800, 1200]} aspectRatio="1:1" />
+```
+
+#### aspectRatio
+
+<p>
+
+**Type:** `number` | `string`<br>
+**Required:** `true`
+</p>
+
+The desired aspect ratio of the output image. This is combined with `widhts` to calculate the final dimensions of each built image.
+
+A `string` can be provided in the form of `{width}:{height}`, ex: `16:9` or `3:4`.
+
+A `number` can also be provided, useful when the aspect ratio is calculated at build time. This can be an inline number such as `1.777` or inlined as a JSX expression like `aspectRatio={16/9}`.
+
+#### formats
+
+<p>
+
+**Type:** Array<'avif' | 'jpeg' | 'png' | 'webp'><br>
+**Default:** `undefined`
+</p>
+
+The output formats to be used in the optimized image. If not provided, `webp` and `avif` will be used in addition to the original image format.
+
+### `getImage`
+
+This is the helper function used by the `<Image />` component to build `<img />` attributes for the transformed image. This helper can be used directly for more complex use cases that aren't currently supported by the `<Image />` component.
+
+This helper takes in an object with the same properties as the `<Image />` component and returns an object with attributes that should be included on the final `<img />` element.
+
+This can helpful if you need to add preload links to a page's `<head>`.
+
+```astro
+---
+import { getImage } from '@astrojs/image';
+
+const { src } = await getImage('../assets/hero.png');
+---
+
+<html>
+ <head>
+ <link rel="preload" as="image" href={src}>
+ </head>
+</html>
+```
+
+### `getPicture`
+
+This is the helper function used by the `<Picture />` component to build multiple sizes and formats for responsive images. This helper can be used directly for more complex use cases that aren't currently supported by the `<Picture />` component.
+
+This helper takes in an object with the same properties as the `<Picture />` component and returns an object attributes that should be included on the final `<img />` element **and** a list of sources that should be used to render all `<source>`s for the `<picture>` element.
## Configuration
@@ -102,7 +296,7 @@ export default {
Image files in your project's `src` directory can be imported in frontmatter and passed directly to the `<Image />` component. All other properties are optional and will default to the original image file's properties if not provided.
-```html
+```astro
---
import { Image } from '@astrojs/image/components';
import heroImage from '../assets/hero.png';
@@ -130,7 +324,7 @@ import heroImage from '../assets/hero.png';
Remote images can be transformed with the `<Image />` component. The `<Image />` component needs to know the final dimensions for the `<img />` element to avoid content layout shifts. For remote images, this means you must either provide `width` and `height`, or one of the dimensions plus the required `aspectRatio`.
-```html
+```astro
---
import { Image } from '@astrojs/image/components';
@@ -149,28 +343,6 @@ const imageUrl = 'https://www.google.com/images/branding/googlelogo/2x/googlelog
</details>
<details>
-<summary><strong>Images in markdown</strong></summary>
-
- The `<Image />` component can also be used to optimize images in markdown pages. For local images imported from your project's `src` directory, use Astro's the `setup` frontmatter to import the image file.
-
-```html
----
-setup: |
- import { Image } from '@astrojs/image/components'
- import hero from '../../assets/blog/introducing-astro.jpg'
-title: Hello world!
-publishDate: 12 Sep 2021
-name: Nate Moore
-value: 128
-description: Just a Hello World Post!
----
-
-<Image src={hero} width={640} />
-<Image src="https://example.com/image.jpg" width={640} aspectRatio="16:9" />
-```
-</details>
-
-<details>
<summary><strong>Responsive pictures</strong></summary>
The `<Picture />` component can be used to automatically build a `<picture>` with multiple sizes and formats. Check out [MDN](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#art_direction) for a deep dive into responsive images and art direction.
@@ -179,7 +351,7 @@ description: Just a Hello World Post!
For remote images, an `aspectRatio` is required to ensure the correct `height` can be calculated at build time.
-```html
+```astro
---
import { Picture } from '@astrojs/image/components';
import hero from '../assets/hero.png';
diff --git a/packages/integrations/image/client.d.ts b/packages/integrations/image/client.d.ts
new file mode 100644
index 000000000..c736d2f44
--- /dev/null
+++ b/packages/integrations/image/client.d.ts
@@ -0,0 +1,55 @@
+type InputFormat =
+ | 'avif'
+ | 'gif'
+ | 'heic'
+ | 'heif'
+ | 'jpeg'
+ | 'jpg'
+ | 'png'
+ | 'tiff'
+ | 'webp';
+
+interface ImageMetadata {
+ src: string;
+ width: number;
+ height: number;
+ format: InputFormat;
+}
+
+// images
+declare module '*.avif' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.gif' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.heic' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.heif' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.jpeg' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.jpg' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.png' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.tiff' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
+declare module '*.webp' {
+ const metadata: ImageMetadata;
+ export default metadata;
+}
diff --git a/packages/integrations/image/components/Image.astro b/packages/integrations/image/components/Image.astro
index 18e35d1a6..c38814c9e 100644
--- a/packages/integrations/image/components/Image.astro
+++ b/packages/integrations/image/components/Image.astro
@@ -1,13 +1,16 @@
---
// @ts-ignore
import { getImage } from '../dist/index.js';
-import type { ImageAttributes, ImageMetadata, TransformOptions, OutputFormat } from '../dist/types';
+import type { ImgHTMLAttributes } from './index.js';
+import type { ImageMetadata, TransformOptions, OutputFormat } from '../dist/index.js';
-export interface LocalImageProps extends Omit<TransformOptions, 'src'>, Omit<ImageAttributes, 'src' | 'width' | 'height'> {
+interface LocalImageProps extends
+ Omit<TransformOptions, 'src'>,
+ Omit<ImgHTMLAttributes, | 'src' | 'width' | 'height'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
}
-export interface RemoteImageProps extends TransformOptions, ImageAttributes {
+interface RemoteImageProps extends TransformOptions, astroHTML.JSX.ImgHTMLAttributes {
src: string;
format: OutputFormat;
width: number;
diff --git a/packages/integrations/image/components/Picture.astro b/packages/integrations/image/components/Picture.astro
index badfc7f46..372fcbb1b 100644
--- a/packages/integrations/image/components/Picture.astro
+++ b/packages/integrations/image/components/Picture.astro
@@ -1,8 +1,12 @@
---
import { getPicture } from '../dist/index.js';
-import type { ImageAttributes, ImageMetadata, OutputFormat, PictureAttributes, TransformOptions } from '../dist/types';
+import type { ImgHTMLAttributes, HTMLAttributes } from './index.js';
+import type { ImageMetadata, OutputFormat, TransformOptions } from '../dist/index.js';
-export interface LocalImageProps extends Omit<PictureAttributes, 'src' | 'width' | 'height'>, Omit<TransformOptions, 'src'>, Pick<ImageAttributes, 'loading' | 'decoding'> {
+interface LocalImageProps extends
+ Omit<HTMLAttributes, 'src' | 'width' | 'height'>,
+ Omit<TransformOptions, 'src'>,
+ Pick<astroHTML.JSX.ImgHTMLAttributes, 'loading' | 'decoding'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
alt?: string;
sizes: HTMLImageElement['sizes'];
@@ -10,7 +14,10 @@ export interface LocalImageProps extends Omit<PictureAttributes, 'src' | 'width'
formats?: OutputFormat[];
}
-export interface RemoteImageProps extends Omit<PictureAttributes, 'src' | 'width' | 'height'>, TransformOptions, Pick<ImageAttributes, 'loading' | 'decoding'> {
+interface RemoteImageProps extends
+ Omit<HTMLAttributes, 'src' | 'width' | 'height'>,
+ TransformOptions,
+ Pick<ImgHTMLAttributes, 'loading' | 'decoding'> {
src: string;
alt?: string;
sizes: HTMLImageElement['sizes'];
diff --git a/packages/integrations/image/components/index.ts b/packages/integrations/image/components/index.ts
index be0e10130..088278fc2 100644
--- a/packages/integrations/image/components/index.ts
+++ b/packages/integrations/image/components/index.ts
@@ -1,2 +1,7 @@
+/// <reference types="astro/astro-jsx" />
export { default as Image } from './Image.astro';
export { default as Picture } from './Picture.astro';
+
+// 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<astroHTML.JSX.HTMLAttributes, 'client:list' | 'set:text' | 'set:html' | 'is:raw'>;
diff --git a/packages/integrations/image/package.json b/packages/integrations/image/package.json
index e1dfeed8e..fb8635eb1 100644
--- a/packages/integrations/image/package.json
+++ b/packages/integrations/image/package.json
@@ -3,7 +3,7 @@
"description": "Load and transform images in your Astro site.",
"version": "0.2.0",
"type": "module",
- "types": "./dist/types.d.ts",
+ "types": "./dist/index.d.ts",
"author": "withastro",
"license": "MIT",
"repository": {
@@ -20,21 +20,18 @@
"bugs": "https://github.com/withastro/astro/issues",
"homepage": "https://docs.astro.build/en/guides/integrations-guide/image/",
"exports": {
- ".": {
- "astro": "./components/index.js",
- "import": "./dist/index.js"
- },
+ ".": "./dist/index.js",
"./sharp": "./dist/loaders/sharp.js",
"./endpoints/dev": "./dist/endpoints/dev.js",
"./endpoints/prod": "./dist/endpoints/prod.js",
"./components": "./components/index.js",
- "./package.json": "./package.json"
+ "./package.json": "./package.json",
+ "./client": "./client.d.ts"
},
"files": [
"components",
"dist",
- "src",
- "types"
+ "client.d.ts"
],
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
diff --git a/packages/integrations/image/src/build/ssg.ts b/packages/integrations/image/src/build/ssg.ts
index 78510889c..496905f92 100644
--- a/packages/integrations/image/src/build/ssg.ts
+++ b/packages/integrations/image/src/build/ssg.ts
@@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { OUTPUT_DIR } from '../constants.js';
-import type { SSRImageService, TransformOptions } from '../types.js';
+import type { SSRImageService, TransformOptions } from '../loaders/index.js';
import { isRemoteImage, loadLocalImage, loadRemoteImage } from '../utils/images.js';
import { ensureDir } from '../utils/paths.js';
diff --git a/packages/integrations/image/src/index.ts b/packages/integrations/image/src/index.ts
index 81ef8c6b9..234b1646d 100644
--- a/packages/integrations/image/src/index.ts
+++ b/packages/integrations/image/src/index.ts
@@ -1,5 +1,116 @@
-import integration from './integration.js';
-export * from './lib/get-image.js';
-export * from './lib/get-picture.js';
+import type { AstroConfig, AstroIntegration } from 'astro';
+import { ssgBuild } from './build/ssg.js';
+import { ssrBuild } from './build/ssr.js';
+import { PKG_NAME, ROUTE_PATTERN } from './constants.js';
+import { ImageService, TransformOptions } from './loaders/index.js';
+import { filenameFormat, propsToFilename } from './utils/paths.js';
+import { createPlugin } from './vite-plugin-astro-image.js';
-export default integration;
+export { getImage } from './lib/get-image.js';
+export { getPicture } from './lib/get-picture.js';
+export * from './loaders/index.js';
+export type { ImageMetadata} from './vite-plugin-astro-image.js';
+
+interface ImageIntegration {
+ loader?: ImageService;
+ addStaticImage?: (transform: TransformOptions) => void;
+ filenameFormat?: (transform: TransformOptions, searchParams: URLSearchParams) => string;
+}
+
+declare global {
+ // eslint-disable-next-line no-var
+ var astroImage: ImageIntegration | undefined;
+}
+
+export interface IntegrationOptions {
+ /**
+ * Entry point for the @type {HostedImageService} or @type {LocalImageService} to be used.
+ */
+ serviceEntryPoint?: string;
+}
+
+export default function integration(options: IntegrationOptions = {}): AstroIntegration {
+ const resolvedOptions = {
+ serviceEntryPoint: '@astrojs/image/sharp',
+ ...options,
+ };
+
+ // During SSG builds, this is used to track all transformed images required.
+ const staticImages = new Map<string, Map<string, TransformOptions>>();
+
+ let _config: AstroConfig;
+ let output: 'server' | 'static';
+
+ function getViteConfiguration() {
+ return {
+ plugins: [createPlugin(_config, resolvedOptions)],
+ optimizeDeps: {
+ include: ['image-size', 'sharp'],
+ },
+ ssr: {
+ noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint],
+ },
+ };
+ }
+
+ return {
+ name: PKG_NAME,
+ hooks: {
+ 'astro:config:setup': ({ command, config, injectRoute, updateConfig }) => {
+ _config = config;
+
+ // Always treat `astro dev` as SSR mode, even without an adapter
+ output = command === 'dev' ? 'server' : config.output;
+
+ updateConfig({ vite: getViteConfiguration() });
+
+ if (output === 'server') {
+ injectRoute({
+ pattern: ROUTE_PATTERN,
+ entryPoint:
+ command === 'dev' ? '@astrojs/image/endpoints/dev' : '@astrojs/image/endpoints/prod',
+ });
+ }
+ },
+ 'astro:server:setup': async () => {
+ globalThis.astroImage = {};
+ },
+ 'astro:build:setup': () => {
+ // Used to cache all images rendered to HTML
+ // Added to globalThis to share the same map in Node and Vite
+ function addStaticImage(transform: TransformOptions) {
+ const srcTranforms = staticImages.has(transform.src)
+ ? staticImages.get(transform.src)!
+ : new Map<string, TransformOptions>();
+
+ srcTranforms.set(propsToFilename(transform), transform);
+
+ staticImages.set(transform.src, srcTranforms);
+ }
+
+ // Helpers for building static images should only be available for SSG
+ globalThis.astroImage =
+ output === 'static'
+ ? {
+ addStaticImage,
+ filenameFormat,
+ }
+ : {};
+ },
+ 'astro:build:done': async ({ dir }) => {
+ if (output === 'server') {
+ // for SSR builds, copy all image files from src to dist
+ // to make sure they are available for use in production
+ await ssrBuild({ srcDir: _config.srcDir, outDir: dir });
+ } else {
+ // for SSG builds, build all requested image transforms to dist
+ const loader = globalThis?.astroImage?.loader;
+
+ if (loader && 'transform' in loader && staticImages.size > 0) {
+ await ssgBuild({ loader, staticImages, srcDir: _config.srcDir, outDir: dir });
+ }
+ }
+ },
+ },
+ };
+}
diff --git a/packages/integrations/image/src/integration.ts b/packages/integrations/image/src/integration.ts
deleted file mode 100644
index 725276d03..000000000
--- a/packages/integrations/image/src/integration.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import type { AstroConfig, AstroIntegration } from 'astro';
-import { ssgBuild } from './build/ssg.js';
-import { ssrBuild } from './build/ssr.js';
-import { PKG_NAME, ROUTE_PATTERN } from './constants.js';
-import { IntegrationOptions, TransformOptions } from './types.js';
-import { filenameFormat, propsToFilename } from './utils/paths.js';
-import { createPlugin } from './vite-plugin-astro-image.js';
-
-export default function integration(options: IntegrationOptions = {}): AstroIntegration {
- const resolvedOptions = {
- serviceEntryPoint: '@astrojs/image/sharp',
- ...options,
- };
-
- // During SSG builds, this is used to track all transformed images required.
- const staticImages = new Map<string, Map<string, TransformOptions>>();
-
- let _config: AstroConfig;
- let output: 'server' | 'static';
-
- function getViteConfiguration() {
- return {
- plugins: [createPlugin(_config, resolvedOptions)],
- optimizeDeps: {
- include: ['image-size', 'sharp'],
- },
- ssr: {
- noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint],
- },
- };
- }
-
- return {
- name: PKG_NAME,
- hooks: {
- 'astro:config:setup': ({ command, config, injectRoute, updateConfig }) => {
- _config = config;
-
- // Always treat `astro dev` as SSR mode, even without an adapter
- output = command === 'dev' ? 'server' : config.output;
-
- updateConfig({ vite: getViteConfiguration() });
-
- if (output === 'server') {
- injectRoute({
- pattern: ROUTE_PATTERN,
- entryPoint:
- command === 'dev' ? '@astrojs/image/endpoints/dev' : '@astrojs/image/endpoints/prod',
- });
- }
- },
- 'astro:server:setup': async () => {
- globalThis.astroImage = {};
- },
- 'astro:build:setup': () => {
- // Used to cache all images rendered to HTML
- // Added to globalThis to share the same map in Node and Vite
- function addStaticImage(transform: TransformOptions) {
- const srcTranforms = staticImages.has(transform.src)
- ? staticImages.get(transform.src)!
- : new Map<string, TransformOptions>();
-
- srcTranforms.set(propsToFilename(transform), transform);
-
- staticImages.set(transform.src, srcTranforms);
- }
-
- // Helpers for building static images should only be available for SSG
- globalThis.astroImage =
- output === 'static'
- ? {
- addStaticImage,
- filenameFormat,
- }
- : {};
- },
- 'astro:build:done': async ({ dir }) => {
- if (output === 'server') {
- // for SSR builds, copy all image files from src to dist
- // to make sure they are available for use in production
- await ssrBuild({ srcDir: _config.srcDir, outDir: dir });
- } else {
- // for SSG builds, build all requested image transforms to dist
- const loader = globalThis?.astroImage?.loader;
-
- if (loader && 'transform' in loader && staticImages.size > 0) {
- await ssgBuild({ loader, staticImages, srcDir: _config.srcDir, outDir: dir });
- }
- }
- },
- },
- };
-}
diff --git a/packages/integrations/image/src/lib/get-image.ts b/packages/integrations/image/src/lib/get-image.ts
index e0f57e873..0a28ff3ac 100644
--- a/packages/integrations/image/src/lib/get-image.ts
+++ b/packages/integrations/image/src/lib/get-image.ts
@@ -1,15 +1,15 @@
+/// <reference types="astro/astro-jsx" />
import slash from 'slash';
import { ROUTE_PATTERN } from '../constants.js';
import sharp from '../loaders/sharp.js';
import {
- ImageAttributes,
- ImageMetadata,
ImageService,
isSSRService,
OutputFormat,
TransformOptions,
-} from '../types.js';
+} from '../loaders/index.js';
import { isRemoteImage, parseAspectRatio } from '../utils/images.js';
+import { ImageMetadata } from '../vite-plugin-astro-image.js';
export interface GetImageTransform extends Omit<TransformOptions, 'src'> {
src: string | ImageMetadata | Promise<{ default: ImageMetadata }>;
@@ -101,7 +101,7 @@ async function resolveTransform(input: GetImageTransform): Promise<TransformOpti
* @param transform @type {TransformOptions} The transformations requested for the optimized image.
* @returns @type {ImageAttributes} The HTML attributes to be included on the built `<img />` element.
*/
-export async function getImage(transform: GetImageTransform): Promise<ImageAttributes> {
+export async function getImage(transform: GetImageTransform): Promise<astroHTML.JSX.ImgHTMLAttributes> {
if (!transform.src) {
throw new Error('[@astrojs/image] `src` is required');
}
diff --git a/packages/integrations/image/src/lib/get-picture.ts b/packages/integrations/image/src/lib/get-picture.ts
index 82bf9f7c5..0b9521853 100644
--- a/packages/integrations/image/src/lib/get-picture.ts
+++ b/packages/integrations/image/src/lib/get-picture.ts
@@ -1,7 +1,9 @@
+/// <reference types="astro/astro-jsx" />
import { lookup } from 'mrmime';
import { extname } from 'node:path';
-import { ImageAttributes, ImageMetadata, OutputFormat, TransformOptions } from '../types.js';
+import { OutputFormat, TransformOptions } from '../loaders/index.js';
import { parseAspectRatio } from '../utils/images.js';
+import { ImageMetadata } from '../vite-plugin-astro-image.js';
import { getImage } from './get-image.js';
export interface GetPictureParams {
@@ -12,7 +14,7 @@ export interface GetPictureParams {
}
export interface GetPictureResult {
- image: ImageAttributes;
+ image: astroHTML.JSX.HTMLAttributes;
sources: { type: string; srcset: string }[];
}
diff --git a/packages/integrations/image/src/types.ts b/packages/integrations/image/src/loaders/index.ts
index f7e0c0e5f..7681f25d4 100644
--- a/packages/integrations/image/src/types.ts
+++ b/packages/integrations/image/src/loaders/index.ts
@@ -1,17 +1,4 @@
/// <reference types="astro/astro-jsx" />
-export * from './index.js';
-
-interface ImageIntegration {
- loader?: ImageService;
- addStaticImage?: (transform: TransformOptions) => void;
- filenameFormat?: (transform: TransformOptions, searchParams: URLSearchParams) => string;
-}
-
-declare global {
- // eslint-disable-next-line no-var
- var astroImage: ImageIntegration | undefined;
-}
-
export type InputFormat =
| 'heic'
| 'heif'
@@ -26,21 +13,6 @@ export type InputFormat =
export type OutputFormat = 'avif' | 'jpeg' | 'png' | 'webp';
/**
- * Converts a set of image transforms to the filename to use when building for static.
- *
- * This is only used for static production builds and ignored when an SSR adapter is used,
- * or in `astro dev` for static builds.
- */
-export type FilenameFormatter = (transform: TransformOptions) => string;
-
-export interface IntegrationOptions {
- /**
- * Entry point for the @type {HostedImageService} or @type {LocalImageService} to be used.
- */
- serviceEntryPoint?: string;
-}
-
-/**
* Defines the original image and transforms that need to be applied to it.
*/
export interface TransformOptions {
@@ -83,22 +55,19 @@ export interface TransformOptions {
aspectRatio?: number | `${number}:${number}`;
}
-export type ImageAttributes = astroHTML.JSX.ImgHTMLAttributes;
-export type PictureAttributes = astroHTML.JSX.HTMLAttributes;
-
export interface HostedImageService<T extends TransformOptions = TransformOptions> {
/**
* Gets the HTML attributes needed for the server rendered `<img />` element.
*/
- getImageAttributes(transform: T): Promise<ImageAttributes>;
+ getImageAttributes(transform: T): Promise<astroHTML.JSX.ImgHTMLAttributes>;
}
export interface SSRImageService<T extends TransformOptions = TransformOptions>
extends HostedImageService<T> {
/**
- * Gets tthe HTML attributes needed for the server rendered `<img />` element.
+ * Gets the HTML attributes needed for the server rendered `<img />` element.
*/
- getImageAttributes(transform: T): Promise<Exclude<ImageAttributes, 'src'>>;
+ getImageAttributes(transform: T): Promise<Exclude<astroHTML.JSX.ImgHTMLAttributes, 'src'>>;
/**
* Serializes image transformation properties to URLSearchParams, used to build
* the final `src` that points to the self-hosted SSR endpoint.
@@ -134,10 +103,3 @@ export function isHostedService(service: ImageService): service is ImageService
export function isSSRService(service: ImageService): service is SSRImageService {
return 'transform' in service;
}
-
-export interface ImageMetadata {
- src: string;
- width: number;
- height: number;
- format: InputFormat;
-}
diff --git a/packages/integrations/image/src/loaders/sharp.ts b/packages/integrations/image/src/loaders/sharp.ts
index b4c5e18fd..f76a16d39 100644
--- a/packages/integrations/image/src/loaders/sharp.ts
+++ b/packages/integrations/image/src/loaders/sharp.ts
@@ -1,5 +1,5 @@
import sharp from 'sharp';
-import type { OutputFormat, SSRImageService, TransformOptions } from '../types.js';
+import type { OutputFormat, SSRImageService, TransformOptions } from './index.js';
import { isAspectRatioString, isOutputFormat } from '../utils/images.js';
class SharpService implements SSRImageService {
diff --git a/packages/integrations/image/src/utils/images.ts b/packages/integrations/image/src/utils/images.ts
index d36c64fc0..f3c519657 100644
--- a/packages/integrations/image/src/utils/images.ts
+++ b/packages/integrations/image/src/utils/images.ts
@@ -1,5 +1,5 @@
import fs from 'node:fs/promises';
-import type { OutputFormat, TransformOptions } from '../types.js';
+import type { OutputFormat, TransformOptions } from '../loaders/index.js';
export function isOutputFormat(value: string): value is OutputFormat {
return ['avif', 'jpeg', 'png', 'webp'].includes(value);
diff --git a/packages/integrations/image/src/utils/metadata.ts b/packages/integrations/image/src/utils/metadata.ts
index fa60281b6..349a37535 100644
--- a/packages/integrations/image/src/utils/metadata.ts
+++ b/packages/integrations/image/src/utils/metadata.ts
@@ -1,6 +1,7 @@
import sizeOf from 'image-size';
import fs from 'node:fs/promises';
-import { ImageMetadata, InputFormat } from '../types.js';
+import { InputFormat } from '../loaders/index.js';
+import { ImageMetadata } from '../vite-plugin-astro-image.js';
export async function metadata(src: string): Promise<ImageMetadata | undefined> {
const file = await fs.readFile(src);
diff --git a/packages/integrations/image/src/utils/paths.ts b/packages/integrations/image/src/utils/paths.ts
index a958d4911..6258d392d 100644
--- a/packages/integrations/image/src/utils/paths.ts
+++ b/packages/integrations/image/src/utils/paths.ts
@@ -1,7 +1,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { OUTPUT_DIR } from '../constants.js';
-import type { TransformOptions } from '../types.js';
+import type { TransformOptions } from '../loaders/index.js';
import { isRemoteImage } from './images.js';
import { shorthash } from './shorthash.js';
diff --git a/packages/integrations/image/src/vite-plugin-astro-image.ts b/packages/integrations/image/src/vite-plugin-astro-image.ts
index 81593c142..aefc910bb 100644
--- a/packages/integrations/image/src/vite-plugin-astro-image.ts
+++ b/packages/integrations/image/src/vite-plugin-astro-image.ts
@@ -3,9 +3,17 @@ import { pathToFileURL } from 'node:url';
import type { PluginContext } from 'rollup';
import slash from 'slash';
import type { Plugin, ResolvedConfig } from 'vite';
-import type { IntegrationOptions } from './types.js';
+import type { IntegrationOptions } from './index.js';
+import type { InputFormat } from './loaders/index.js';
import { metadata } from './utils/metadata.js';
+export interface ImageMetadata {
+ src: string;
+ width: number;
+ height: number;
+ format: InputFormat;
+}
+
export function createPlugin(config: AstroConfig, options: Required<IntegrationOptions>): Plugin {
const filter = (id: string) =>
/^(?!\/_image?).*.(heic|heif|avif|jpeg|jpg|png|tiff|webp|gif)$/.test(id);