diff --git a/.changeset/modern-bears-deny.md b/.changeset/modern-bears-deny.md new file mode 100644 index 000000000000..876535a5c033 --- /dev/null +++ b/.changeset/modern-bears-deny.md @@ -0,0 +1,16 @@ +--- +'astro': major +--- + +Makes the `compiledContent` property of Markdown content an async function, this change should fix underlying issues where sometimes when using a custom image service and images inside Markdown, Node would exit suddenly without any error message. + +```diff +--- +import * as myPost from "../post.md"; + +- const content = myPost.compiledContent(); ++ const content = await myPost.compiledContent(); +--- + + +``` diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 57bbf847a4ff..f7c541eb6265 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -2,7 +2,6 @@ import { extname } from 'node:path'; import MagicString from 'magic-string'; import type * as vite from 'vite'; import { normalizePath } from 'vite'; -import { extendManualChunks } from '../core/build/plugins/util.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; import { appendForwardSlash, @@ -106,19 +105,6 @@ export default function assets({ // Expose the components and different utilities from `astro:assets` and handle serving images from `/_image` in dev { name: 'astro:assets', - outputOptions(outputOptions) { - // Specifically split out chunk for asset files to prevent TLA deadlock - // caused by `getImage()` for markdown components. - // https://github.com/rollup/rollup/issues/4708 - extendManualChunks(outputOptions, { - after(id) { - if (id.includes('astro/dist/assets/services/')) { - // By convention, library code is emitted to the `chunks/astro/*` directory - return `astro/assets-service`; - } - }, - }); - }, async resolveId(id) { if (id === VIRTUAL_SERVICE_ID) { return await this.resolve(settings.config.image.service.entrypoint); diff --git a/packages/astro/src/types/public/content.ts b/packages/astro/src/types/public/content.ts index ac58c918f48f..77c0b2f17620 100644 --- a/packages/astro/src/types/public/content.ts +++ b/packages/astro/src/types/public/content.ts @@ -21,7 +21,7 @@ export interface MarkdownInstance> { /** raw Markdown file content, excluding layout HTML and YAML frontmatter */ rawContent(): string; /** Markdown file compiled to HTML, excluding layout HTML */ - compiledContent(): string; + compiledContent(): Promise; /** List of headings (h1 -> h6) with associated metadata */ getHeadings(): MarkdownHeading[]; default: AstroComponentFactory; diff --git a/packages/astro/src/vite-plugin-markdown/images.ts b/packages/astro/src/vite-plugin-markdown/images.ts index b9ea98b82b50..d0ed625358ff 100644 --- a/packages/astro/src/vite-plugin-markdown/images.ts +++ b/packages/astro/src/vite-plugin-markdown/images.ts @@ -23,7 +23,6 @@ export function getMarkdownCodeForImages(imagePaths: MarkdownImagePath[], html: const matchKey = ${rawUrl} + '_' + occurrenceCounter; const imageProps = JSON.parse(match[1].replace(/"/g, '"')); const { src, ...props } = imageProps; - imageSources[matchKey] = await getImage({src: Astro__${entry.safeName}, ...props}); occurrenceCounter++; } @@ -33,32 +32,28 @@ export function getMarkdownCodeForImages(imagePaths: MarkdownImagePath[], html: return imageSources; }; - async function updateImageReferences(html) { - return images(html).then((imageSources) => { - return html.replaceAll(/__ASTRO_IMAGE_="([^"]+)"/gm, (full, imagePath) => { - const decodedImagePath = JSON.parse(imagePath.replace(/"/g, '"')); - - // Use the 'index' property for each image occurrence - const srcKey = decodedImagePath.src + '_' + decodedImagePath.index; - - if (imageSources[srcKey].srcSet && imageSources[srcKey].srcSet.values.length > 0) { - imageSources[srcKey].attributes.srcset = imageSources[srcKey].srcSet.attribute; - } - - const { index, ...attributesWithoutIndex } = imageSources[srcKey].attributes; - - return spreadAttributes({ - src: imageSources[srcKey].src, - ...attributesWithoutIndex, - }); - }); + async function updateImageReferences(html) { + const imageSources = await images(html); + + return html.replaceAll(/__ASTRO_IMAGE_="([^"]+)"/gm, (full, imagePath) => { + const decodedImagePath = JSON.parse(imagePath.replace(/"/g, '"')); + + // Use the 'index' property for each image occurrence + const srcKey = decodedImagePath.src + '_' + decodedImagePath.index; + + if (imageSources[srcKey].srcSet && imageSources[srcKey].srcSet.values.length > 0) { + imageSources[srcKey].attributes.srcset = imageSources[srcKey].srcSet.attribute; + } + + const { index, ...attributesWithoutIndex } = imageSources[srcKey].attributes; + + return spreadAttributes({ + src: imageSources[srcKey].src, + ...attributesWithoutIndex, }); + }); } - - // NOTE: This causes a top-level await to appear in the user's code, which can break very easily due to a Rollup - // bug and certain adapters not supporting it correctly. See: https://github.com/rollup/rollup/issues/4708 - // Tread carefully! - const html = await updateImageReferences(${JSON.stringify(html)}); + const html = async () => await updateImageReferences(${JSON.stringify(html)}); `; } diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index 694b96448fb5..a85eaff4659c 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -115,7 +115,7 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug // Only include the code relevant to `astro:assets` if there's images in the file imagePaths.length > 0 ? getMarkdownCodeForImages(imagePaths, html) - : `const html = ${JSON.stringify(html)};` + : `const html = () => ${JSON.stringify(html)};` } export const frontmatter = ${JSON.stringify(frontmatter)}; @@ -124,8 +124,8 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug export function rawContent() { return ${JSON.stringify(raw.content)}; } - export function compiledContent() { - return html; + export async function compiledContent() { + return await html(); } export function getHeadings() { return ${JSON.stringify(headings)}; @@ -148,9 +148,9 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug compiledContent, 'server:root': true, }, { - 'default': () => render\`\${unescapeHTML(html)}\` + 'default': () => render\`\${unescapeHTML(html())}\` })}\`;` - : `render\`\${maybeRenderHead(result)}\${unescapeHTML(html)}\`;` + : `render\`\${maybeRenderHead(result)}\${unescapeHTML(html())}\`;` } }); export default Content;