Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/busy-olives-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
'astro': major
---

Removes the deprecated `emitESMImage()` function

In Astro 5.6.2, the `emitESMImage()` function was deprecated in favor of `emitImageMetadata()`, which removes two deprecated arguments that were not meant to be exposed for public use: `_watchMode` and `experimentalSvgEnabled`.

Astro 6.0 removes `emitESMImage()` entirely. Update to `emitImageMetadata()` to keep your current behavior.

#### What should I do?

Replace all occurrences of the `emitESMImage()` with `emitImageMetadata()` and remove unused arguments:

```ts del={1,5} ins={2,6}
import { emitESMImage } from 'astro/assets/utils';
import { emitImageMetadata } from 'astro/assets/utils';

const imageId = '/images/photo.jpg';
const result = await emitESMImage(imageId, false, false);
const result = await emitImageMetadata(imageId);
```
8 changes: 1 addition & 7 deletions packages/astro/src/assets/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@

export { isESMImportedImage, isRemoteImage, resolveSrc } from './imageKind.js';
export { imageMetadata } from './metadata.js';
export {
/**
* @deprecated
*/
emitESMImage,
emitImageMetadata,
} from './node/emitAsset.js';
export { emitImageMetadata } from './node/emitAsset.js';
export { getOrigQueryParams } from './queryParams.js';
export {
isRemoteAllowed,
Expand Down
85 changes: 0 additions & 85 deletions packages/astro/src/assets/utils/node/emitAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,91 +59,6 @@ async function handleSvgDeduplication(
}
}

/**
* Processes an image file and emits its metadata and optionally its contents. This function supports both build and development modes.
*
* @param {string | undefined} id - The identifier or path of the image file to process. If undefined, the function returns immediately.
* @param {boolean} _watchMode - **Deprecated**: Indicates if the method is operating in watch mode. This parameter will be removed or updated in the future.
* @param {boolean} _experimentalSvgEnabled - **Deprecated**: A flag to enable experimental handling of SVG files. Embeds SVG file data if set to true.
* @param {FileEmitter | undefined} [fileEmitter] - Function for emitting files during the build process. May throw in certain scenarios.
* @return {Promise<ImageMetadataWithContents | undefined>} Resolves to metadata with optional image contents or `undefined` if processing fails.
*/
// We want to internally use this function until we fix the memory in the SVG features
export async function emitESMImage(
id: string | undefined,
/** @deprecated */
_watchMode: boolean,
// FIX: in Astro 6, this function should not be passed in dev mode at all.
// Or rethink the API so that a function that throws isn't passed through.
/** @deprecated */
_experimentalSvgEnabled: boolean,
fileEmitter?: FileEmitter,
): Promise<ImageMetadataWithContents | undefined> {
if (!id) {
return undefined;
}

const url = pathToFileURL(id);
let fileData: Buffer;
try {
fileData = await fs.readFile(url);
} catch {
return undefined;
}

const fileMetadata = await imageMetadata(fileData, id);

const emittedImage: Omit<ImageMetadataWithContents, 'fsPath'> = {
src: '',
...fileMetadata,
};

// Private for now, we generally don't want users to rely on filesystem paths, but we need it so that we can maybe remove the original asset from the build if it's unused.
Object.defineProperty(emittedImage, 'fsPath', {
enumerable: false,
writable: false,
value: id,
});

// Build
let isBuild = typeof fileEmitter === 'function';
if (isBuild) {
const pathname = decodeURI(url.pathname);
const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`);

try {
let handle: string;

if (fileMetadata.format === 'svg') {
// check if this content already exists
handle = await handleSvgDeduplication(fileData, filename, fileEmitter!);
} else {
// Non-SVG assets: emit normally
handle = fileEmitter!({
name: filename,
source: fileData,
type: 'asset',
});
}

emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`;
} catch {
isBuild = false;
}
}

if (!isBuild) {
// Pass the original file information through query params so we don't have to load the file twice
url.searchParams.append('origWidth', fileMetadata.width.toString());
url.searchParams.append('origHeight', fileMetadata.height.toString());
url.searchParams.append('origFormat', fileMetadata.format);

emittedImage.src = `/@fs` + prependForwardSlash(fileURLToNormalizedPath(url));
}

return emittedImage as ImageMetadataWithContents;
}

/**
* Processes an image file and emits its metadata and optionally its contents. This function supports both build and development modes.
*
Expand Down
11 changes: 3 additions & 8 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { fontsPlugin } from './fonts/vite-plugin-fonts.js';
import type { ImageTransform } from './types.js';
import { getAssetsPrefix } from './utils/getAssetsPrefix.js';
import { isESMImportedImage } from './utils/imageKind.js';
import { emitESMImage } from './utils/node/emitAsset.js';
import { emitImageMetadata } from './utils/node/emitAsset.js';
import { getProxyCode } from './utils/proxy.js';
import { makeSvgComponent } from './utils/svg.js';
import { hashTransform, propsToFilename } from './utils/transformToPath.js';
Expand Down Expand Up @@ -221,13 +221,8 @@ export default function assets({ fs, settings, sync, logger }: Options): vite.Pl
return;
}

const emitFile = shouldEmitFile ? this.emitFile.bind(this) : undefined;
const imageMetadata = await emitESMImage(
id,
this.meta.watchMode,
id.endsWith('.svg'),
emitFile,
);
const fileEmitter = shouldEmitFile ? this.emitFile.bind(this) : undefined;
const imageMetadata = await emitImageMetadata(id, fileEmitter);

if (!imageMetadata) {
throw new AstroError({
Expand Down
2 changes: 0 additions & 2 deletions packages/astro/src/content/content-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,6 @@ class ContentLayer {
},
collectionWithResolvedSchema,
false,
// FUTURE: Remove in this in v6
id.endsWith('.svg'),
);

return parsedData;
Expand Down
8 changes: 2 additions & 6 deletions packages/astro/src/content/runtime-assets.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import type { PluginContext } from 'rollup';
import { z } from 'zod';
import type { ImageMetadata, OmitBrand } from '../assets/types.js';
import { emitESMImage } from '../assets/utils/node/emitAsset.js';
import { emitImageMetadata } from '../assets/utils/node/emitAsset.js';

export function createImage(
pluginContext: PluginContext,
shouldEmitFile: boolean,
entryFilePath: string,
experimentalSvgEnabled: boolean,
) {
return () => {
return z.string().transform(async (imagePath, ctx) => {
const resolvedFilePath = (await pluginContext.resolve(imagePath, entryFilePath))?.id;
const metadata = (await emitESMImage(
const metadata = (await emitImageMetadata(
resolvedFilePath,
pluginContext.meta.watchMode,
// FUTURE: Remove in this in v6
experimentalSvgEnabled,
shouldEmitFile ? pluginContext.emitFile : undefined,
)) as OmitBrand<ImageMetadata>;

Expand Down
10 changes: 1 addition & 9 deletions packages/astro/src/content/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ export async function getEntryDataAndImages<
},
collectionConfig: CollectionConfig,
shouldEmitFile: boolean,
experimentalSvgEnabled: boolean,
pluginContext?: PluginContext,
): Promise<{ data: TOutputData; imageImports: Array<string> }> {
let data = entry.unvalidatedData as TOutputData;
Expand All @@ -145,12 +144,7 @@ export async function getEntryDataAndImages<
if (typeof schema === 'function') {
if (pluginContext) {
schema = schema({
image: createImage(
pluginContext,
shouldEmitFile,
entry._internal.filePath,
experimentalSvgEnabled,
),
image: createImage(pluginContext, shouldEmitFile, entry._internal.filePath),
});
} else if (collectionConfig.type === CONTENT_LAYER_TYPE) {
schema = schema({
Expand Down Expand Up @@ -211,14 +205,12 @@ export async function getEntryData(
},
collectionConfig: CollectionConfig,
shouldEmitFile: boolean,
experimentalSvgEnabled: boolean,
pluginContext?: PluginContext,
) {
const { data } = await getEntryDataAndImages(
entry,
collectionConfig,
shouldEmitFile,
experimentalSvgEnabled,
pluginContext,
);
return data;
Expand Down
4 changes: 0 additions & 4 deletions packages/astro/src/content/vite-plugin-content-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,6 @@ async function getContentEntryModule(
{ id, collection, _internal, unvalidatedData },
collectionConfig,
params.shouldEmitFile,
// FUTURE: Remove in this in v6
id.endsWith('.svg'),
pluginContext,
)
: unvalidatedData;
Expand Down Expand Up @@ -282,8 +280,6 @@ async function getDataEntryModule(
{ id, collection, _internal, unvalidatedData },
collectionConfig,
params.shouldEmitFile,
// FUTURE: Remove in this in v6
id.endsWith('.svg'),
pluginContext,
)
: unvalidatedData;
Expand Down
10 changes: 2 additions & 8 deletions packages/integrations/markdoc/src/content-entry-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { parseFrontmatter } from '@astrojs/markdown-remark';
import type { Config as MarkdocConfig, Node } from '@markdoc/markdoc';
import Markdoc from '@markdoc/markdoc';
import type { AstroConfig, ContentEntryType } from 'astro';
import { emitESMImage } from 'astro/assets/utils';
import { emitImageMetadata } from 'astro/assets/utils';
import type { Rollup, ErrorPayload as ViteErrorPayload } from 'vite';
import type { ComponentConfig } from './config.js';
import { htmlTokenTransform } from './html/transform/html-token-transform.js';
Expand Down Expand Up @@ -319,13 +319,7 @@ async function emitOptimizedImages(
const resolved = await ctx.pluginContext.resolve(node.attributes.src, ctx.filePath);

if (resolved?.id && fs.existsSync(new URL(prependForwardSlash(resolved.id), 'file://'))) {
const src = await emitESMImage(
resolved.id,
ctx.pluginContext.meta.watchMode,
// FUTURE: Remove in this in v6
resolved.id.endsWith('.svg'),
ctx.pluginContext.emitFile,
);
const src = await emitImageMetadata(resolved.id, ctx.pluginContext.emitFile);

const fsPath = resolved.id;

Expand Down
Loading