mirror of
https://github.com/withastro/astro.git
synced 2025-03-17 23:11:29 -05:00
feat: add experimental responsive images config option (#12378)
* feat: add experimental responsive images config option * Apply suggestions from code review Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update config types * Move config into `images` * Move jsdocs --------- Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
parent
5f328e04bc
commit
84492b07a0
5 changed files with 99 additions and 4 deletions
4
packages/astro/client.d.ts
vendored
4
packages/astro/client.d.ts
vendored
|
@ -47,7 +47,9 @@ declare module 'astro:assets' {
|
|||
getImage: (
|
||||
options: import('./dist/assets/types.js').UnresolvedImageTransform,
|
||||
) => Promise<import('./dist/assets/types.js').GetImageResult>;
|
||||
imageConfig: import('./dist/types/public/config.js').AstroConfig['image'];
|
||||
imageConfig: import('./dist/types/public/config.js').AstroConfig['image'] & {
|
||||
experimentalResponsiveImages: boolean;
|
||||
};
|
||||
getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
|
||||
inferRemoteSize: typeof import('./dist/assets/utils/index.js').inferRemoteSize;
|
||||
Image: typeof import('./components/Image.astro').default;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { WithRequired } from '../type-utils.js';
|
||||
import type { ImageLayout } from '../types/public/index.js';
|
||||
import type { VALID_INPUT_FORMATS, VALID_OUTPUT_FORMATS } from './consts.js';
|
||||
import type { ImageService } from './services/service.js';
|
||||
|
||||
|
@ -151,6 +152,12 @@ type ImageSharedProps<T> = T & {
|
|||
* ```
|
||||
*/
|
||||
quality?: ImageQuality;
|
||||
|
||||
layout?: ImageLayout;
|
||||
|
||||
fit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down' | (string & {});
|
||||
|
||||
position?: string;
|
||||
} & (
|
||||
| {
|
||||
/**
|
||||
|
|
|
@ -115,14 +115,14 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
|
|||
},
|
||||
load(id) {
|
||||
if (id === resolvedVirtualModuleId) {
|
||||
return `
|
||||
return /* ts */ `
|
||||
export { getConfiguredImageService, isLocalService } from "astro/assets";
|
||||
import { getImage as getImageInternal } from "astro/assets";
|
||||
export { default as Image } from "astro/components/Image.astro";
|
||||
export { default as Picture } from "astro/components/Picture.astro";
|
||||
export { inferRemoteSize } from "astro/assets/utils/inferRemoteSize.js";
|
||||
|
||||
export const imageConfig = ${JSON.stringify(settings.config.image)};
|
||||
export const imageConfig = ${JSON.stringify({ ...settings.config.image, experimentalResponsiveImages: settings.config.experimental.responsiveImages })};
|
||||
// This is used by the @astrojs/node integration to locate images.
|
||||
// It's unused on other platforms, but on some platforms like Netlify (and presumably also Vercel)
|
||||
// new URL("dist/...") is interpreted by the bundler as a signal to include that directory
|
||||
|
|
|
@ -95,6 +95,7 @@ export const ASTRO_CONFIG_DEFAULTS = {
|
|||
experimental: {
|
||||
clientPrerender: false,
|
||||
contentIntellisense: false,
|
||||
responsiveImages: false,
|
||||
},
|
||||
} satisfies AstroUserConfig & { server: { open: boolean } };
|
||||
|
||||
|
@ -284,6 +285,9 @@ export const AstroConfigSchema = z.object({
|
|||
}),
|
||||
)
|
||||
.default([]),
|
||||
experimentalLayout: z.enum(['responsive', 'fixed', 'full-width', 'none']).optional(),
|
||||
experimentalObjectFit: z.string().optional(),
|
||||
experimentalObjectPosition: z.string().optional(),
|
||||
})
|
||||
.default(ASTRO_CONFIG_DEFAULTS.image),
|
||||
devToolbar: z
|
||||
|
@ -525,6 +529,10 @@ export const AstroConfigSchema = z.object({
|
|||
.boolean()
|
||||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.experimental.contentIntellisense),
|
||||
responsiveImages: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.experimental.responsiveImages),
|
||||
})
|
||||
.strict(
|
||||
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`,
|
||||
|
@ -688,7 +696,7 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
|
|||
'The value of `outDir` must not point to a path within the folder set as `publicDir`, this will cause an infinite loop',
|
||||
})
|
||||
.superRefine((configuration, ctx) => {
|
||||
const { site, i18n, output } = configuration;
|
||||
const { site, i18n, output, image, experimental } = configuration;
|
||||
const hasDomains = i18n?.domains ? Object.keys(i18n.domains).length > 0 : false;
|
||||
if (hasDomains) {
|
||||
if (!site) {
|
||||
|
@ -705,6 +713,18 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
|
|||
});
|
||||
}
|
||||
}
|
||||
if (
|
||||
!experimental.responsiveImages &&
|
||||
(image.experimentalLayout ||
|
||||
image.experimentalObjectFit ||
|
||||
image.experimentalObjectPosition)
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message:
|
||||
'The `experimentalLayout`, `experimentalObjectFit`, and `experimentalObjectPosition` options are only available when `experimental.responsiveImages` is enabled.',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return AstroConfigRelativeSchema;
|
||||
|
|
|
@ -1070,6 +1070,37 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
|||
|
||||
*/
|
||||
remotePatterns?: Partial<RemotePattern>[];
|
||||
|
||||
/**
|
||||
* @docs
|
||||
* @name image.experimentalLayout
|
||||
* @default `undefined`
|
||||
* @description
|
||||
* The default layout type for responsive images. Can be overridden by the `layout` prop on the image component.
|
||||
* Requires the `experimental.responsiveImages` flag to be enabled.
|
||||
* - `responsive` - The image will scale to fit the container, maintaining its aspect ratio, but will not exceed the specified dimensions.
|
||||
* - `fixed` - The image will maintain its original dimensions.
|
||||
* - `full-width` - The image will scale to fit the container, maintaining its aspect ratio.
|
||||
*/
|
||||
experimentalLayout?: ImageLayout | undefined;
|
||||
/**
|
||||
* @docs
|
||||
* @name image.experimentalObjectFit
|
||||
* @default `"cover"`
|
||||
* @description
|
||||
* The default object-fit value for responsive images. Can be overridden by the `fit` prop on the image component.
|
||||
* Requires the `experimental.responsiveImages` flag to be enabled.
|
||||
*/
|
||||
experimentalObjectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down' | (string & {});
|
||||
/**
|
||||
* @docs
|
||||
* @name image.experimentalObjectPosition
|
||||
* @default `"center"`
|
||||
* @description
|
||||
* The default object-position value for responsive images. Can be overridden by the `position` prop on the image component.
|
||||
* Requires the `experimental.responsiveImages` flag to be enabled.
|
||||
*/
|
||||
experimentalObjectPosition?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1699,9 +1730,44 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
|||
* To use this feature with the Astro VS Code extension, you must also enable the `astro.content-intellisense` option in your VS Code settings. For editors using the Astro language server directly, pass the `contentIntellisense: true` initialization parameter to enable this feature.
|
||||
*/
|
||||
contentIntellisense?: boolean;
|
||||
|
||||
/**
|
||||
* @docs
|
||||
* @name experimental.responsiveImages
|
||||
* @type {boolean}
|
||||
* @default `undefined`
|
||||
* @version 5.0.0
|
||||
* @description
|
||||
*
|
||||
* Enables and configures automatic responsive image options for images in your project. Set to `true` (for no default option passed to your images) or an object with default responsive image configuration options.
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* experimental: {
|
||||
* responsiveImages: {
|
||||
* layout: 'responsive',
|
||||
* },
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, you can add a `layout` option to any `<Image />` component when needed to override your default configuration: `responsive`, `fixed`, `full-width`, or `none`. This attribute is required to transform your images if `responsiveImages.layout` is not configured. Images with a layout value of `undefined` or `none` will not be transformed.
|
||||
*
|
||||
* ```astro
|
||||
* ---
|
||||
* import { Image } from 'astro:assets';
|
||||
* import myImage from '../assets/my_image.png';
|
||||
* ---
|
||||
* <Image src={myImage} alt="A description of my image." layout='fixed' />
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
|
||||
responsiveImages?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export type ImageLayout = 'responsive' | 'fixed' | 'full-width' | 'none';
|
||||
|
||||
/**
|
||||
* Resolved Astro Config
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue