-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement RFC "A core story for images" (#6344)
* feat(assets): Add Vite plugin * feat(images): Set up Image component * fix(types): Attempt to fix type generation * Revert "fix(types): Attempt to fix type generation" This reverts commit 063aa27. * fix(image): Fix image types causing build to fail * feat(image): Implement client side part * feat(services): Allow arbitrary transforms parameters * fix(image): Fix paths and types * config(types): Update config types to provide completions for available services * feat(image): Add serving in dev * feat(image): Improve type error messages * refactor(image): Move sharp's parseParams to baseService * refactor(image): Skip work in dev for remote servies * feat(image): Add support for remote images * feat(image): Add squoosh service * chore: update export map * refactor(image): Abstract attributes handling by services * config(vercel): Remove test image service * feat(image): Support for relative images in Markdown (WIP) * feat(images): Add support for relative images in Markdown * feat(image): Update with RFC feedback * fix(image): Fix alt error on getImage * feat(image): Add support for assets validation through content collections * feat(image): Remove validateTransform * feat(image): Move to assets folder * fix(image): Fix package exports * feat(image): Add static imports references to virtual moduel * fix(image): Fix images from content collections not working when embedded * chore: lockfile * fix(markdown): Fix type * fix(images): Flag enhanced images behing an experimental flag * config(example): Update images example conifg * fix(image): Fix types * fix(image): Fix asset type for strict, allow arbritary input and output formats * chore: fix example check * feat(image): Emit assets for ESM imported images * Add initial core image tests (#6381) * feat(images): Make frontmatter extraction more generic than images for future * feat(image): Add support for building * fix(image): Fix types * fix(images): Fix compatibility with image integration * feat(images): Cuter generation stats * fix(images): Globals are unsafe, it turns out * fix(images): Only generate images if flag is enabled * fix(images): Only create `addStaticImage` in build * feat(images): Add SSR endpoint * fix(images): Only inject route in SSR * Add tests for SSR * Remove console.log * Updated lockfile * rename to satisfy the link gods * skip build tests for now * fix(images): Fix WASM files not being copied in dev * feat(images): Add quality presets * fix build tests running * Remove console.log * Add tests for getImage * Test local services * Test the content collections API * Add tests for quality * Skipping content collections test * feat(image): Add support for `~/assets` alias * test(image): Add tests for aliases in dev * Fix windows + content collections * test(image): Add tests for aliased images and images in Markdown * Fix markdown images being built * Should be posix join * Use the optimized image * fix test * Fixes windows smoke * fix(image): Nits * feat(images): Add automatic update for `env.d.ts` when experimental images are enabled * fix(images): Revert env.d.ts change if the user opted-out of the experimental image support * chore: remove bad image example project * feat(image): Rename `experimental.images` to `experimental.assets` * fix(images): Remove unused code in MDX integration * chore: Remove unrelated change * fix(images): Remove export from astro/components * Fix, esm import on Win * test(images): Add test for format * fix(images): Add `client-image.d.ts` to export map * chore: changeset * fix(images): Adjust with feedback, no more automatic refine, asset() -> image() * fix(images): Fix types * fix(images): Remove unnecessary spread * fix(images): Better types for parseUrl and transform * fix(images): Fix types * fix(images): Adjust from feedback * fix(images): Pass width and height through getHTMLAttributes even if they're not added by the uesr * fix(images): Recusirsively extract frontmatter assets * fix(images): Use a reduce instead * feat(images): Add support for data: URIs * chore: changeset * docs(images): Misc docs fixes * Update .changeset/gold-rocks-cry.md Co-authored-by: Chris Swithinbank <[email protected]> * Update .changeset/gold-rocks-cry.md Co-authored-by: Sarah Rainsberger <[email protected]> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <[email protected]> * Update packages/astro/src/assets/services/service.ts Co-authored-by: Chris Swithinbank <[email protected]> * Update packages/astro/src/assets/services/service.ts Co-authored-by: Chris Swithinbank <[email protected]> * Update packages/astro/src/assets/services/service.ts Co-authored-by: Chris Swithinbank <[email protected]> * Update packages/astro/src/assets/types.ts Co-authored-by: Chris Swithinbank <[email protected]> * Update packages/astro/src/assets/types.ts Co-authored-by: Chris Swithinbank <[email protected]> --------- Co-authored-by: Matthew Phillips <[email protected]> Co-authored-by: Matthew Phillips <[email protected]> Co-authored-by: Chris Swithinbank <[email protected]> Co-authored-by: Sarah Rainsberger <[email protected]>
- Loading branch information
1 parent
377530a
commit 694918a
Showing
113 changed files
with
14,978 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'astro': minor | ||
'@astrojs/mdx': minor | ||
'@astrojs/markdown-remark': minor | ||
--- | ||
|
||
Add a new experimental flag (`experimental.assets`) to enable our new core Assets story. | ||
|
||
This unlocks a few features: | ||
- A new built-in image component and JavaScript API to transform and optimize images. | ||
- Relative images with automatic optimization in Markdown. | ||
- Support for validating assets using content collections. | ||
- and more! | ||
|
||
See [Assets (Experimental)](https://docs.astro.build/en/guides/assets/) on our docs site for more information on how to use this feature! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/// <reference path="./client-base.d.ts" /> | ||
|
||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
import { getImage, type LocalImageProps, type RemoteImageProps } from 'astro:assets'; | ||
import { AstroError, AstroErrorData } from '../dist/core/errors/index.js'; | ||
// The TypeScript diagnostic for JSX props uses the last member of the union to suggest props, so it would be better for | ||
// LocalImageProps to be last. Unfortunately, when we do this the error messages that remote images get are complete nonsense | ||
// Not 100% sure how to fix this, seems to be a TypeScript issue. Unfortunate. | ||
type Props = LocalImageProps | RemoteImageProps; | ||
const props = Astro.props; | ||
if (props.alt === undefined || props.alt === null) { | ||
throw new AstroError(AstroErrorData.ImageMissingAlt); | ||
} | ||
// As a convenience, allow width and height to be string with a number in them, to match HTML's native `img`. | ||
if (typeof props.width === 'string') { | ||
props.width = parseInt(props.width); | ||
} | ||
if (typeof props.height === 'string') { | ||
props.height = parseInt(props.height); | ||
} | ||
const image = await getImage(props); | ||
--- | ||
|
||
<img src={image.src} {...image.attributes} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# assets | ||
|
||
This directory powers the Assets story in Astro. Notably, it contains all the code related to optimizing images and serving them in the different modes Astro can run in (SSG, SSR, dev, build etc). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export const VIRTUAL_MODULE_ID = 'astro:assets'; | ||
export const VIRTUAL_SERVICE_ID = 'virtual:image-service'; | ||
export const VALID_INPUT_FORMATS = [ | ||
'heic', | ||
'heif', | ||
'avif', | ||
'jpeg', | ||
'jpg', | ||
'png', | ||
'tiff', | ||
'webp', | ||
'gif', | ||
] as const; | ||
export const VALID_OUTPUT_FORMATS = ['avif', 'png', 'webp', 'jpeg', 'jpg'] as const; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import mime from 'mime'; | ||
import type { APIRoute } from '../@types/astro.js'; | ||
import { isRemotePath } from '../core/path.js'; | ||
import { getConfiguredImageService } from './internal.js'; | ||
import { isLocalService } from './services/service.js'; | ||
import { etag } from './utils/etag.js'; | ||
|
||
async function loadRemoteImage(src: URL) { | ||
try { | ||
const res = await fetch(src); | ||
|
||
if (!res.ok) { | ||
return undefined; | ||
} | ||
|
||
return Buffer.from(await res.arrayBuffer()); | ||
} catch (err: unknown) { | ||
return undefined; | ||
} | ||
} | ||
|
||
/** | ||
* Endpoint used in SSR to serve optimized images | ||
*/ | ||
export const get: APIRoute = async ({ request }) => { | ||
try { | ||
const imageService = await getConfiguredImageService(); | ||
|
||
if (!isLocalService(imageService)) { | ||
throw new Error('Configured image service is not a local service'); | ||
} | ||
|
||
const url = new URL(request.url); | ||
const transform = await imageService.parseURL(url); | ||
|
||
if (!transform || !transform.src) { | ||
throw new Error('Incorrect transform returned by `parseURL`'); | ||
} | ||
|
||
let inputBuffer: Buffer | undefined = undefined; | ||
|
||
// TODO: handle config subpaths? | ||
const sourceUrl = isRemotePath(transform.src) | ||
? new URL(transform.src) | ||
: new URL(transform.src, url.origin); | ||
inputBuffer = await loadRemoteImage(sourceUrl); | ||
|
||
if (!inputBuffer) { | ||
return new Response('Not Found', { status: 404 }); | ||
} | ||
|
||
const { data, format } = await imageService.transform(inputBuffer, transform); | ||
|
||
return new Response(data, { | ||
status: 200, | ||
headers: { | ||
'Content-Type': mime.getType(format) || '', | ||
'Cache-Control': 'public, max-age=31536000', | ||
ETag: etag(data.toString()), | ||
Date: new Date().toUTCString(), | ||
}, | ||
}); | ||
} catch (err: unknown) { | ||
return new Response(`Server Error: ${err}`, { status: 500 }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export { getConfiguredImageService, getImage } from './internal.js'; | ||
export { baseService } from './services/service.js'; | ||
export { type LocalImageProps, type RemoteImageProps } from './types.js'; | ||
export { imageMetadata } from './utils/metadata.js'; |
Oops, something went wrong.