diff --git a/.changeset/thick-penguins-turn.md b/.changeset/thick-penguins-turn.md new file mode 100644 index 000000000000..7ee77abfaedc --- /dev/null +++ b/.changeset/thick-penguins-turn.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix images not having the proper path when using `base` diff --git a/packages/astro/src/assets/internal.ts b/packages/astro/src/assets/internal.ts index 954347e1be4e..db02b1ea18ec 100644 --- a/packages/astro/src/assets/internal.ts +++ b/packages/astro/src/assets/internal.ts @@ -1,6 +1,8 @@ import fs from 'node:fs'; +import { basename, join } from 'node:path/posix'; import type { StaticBuildOptions } from '../core/build/types.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; +import { prependForwardSlash } from '../core/path.js'; import { isLocalService, type ImageService, type LocalImageService } from './services/service.js'; import type { ImageMetadata, ImageTransform } from './types.js'; @@ -104,8 +106,19 @@ export async function generateImage( clientRoot = buildOpts.settings.config.outDir; } - const fileData = await fs.promises.readFile(new URL('.' + options.src.src, serverRoot)); - const resultData = await imageService.transform(fileData, { ...options, src: options.src.src }); + // The original file's path (the `src` attribute of the ESM imported image passed by the user) + const originalImagePath = options.src.src; + + const fileData = await fs.promises.readFile( + new URL( + '.' + + prependForwardSlash( + join(buildOpts.settings.config.build.assets, basename(originalImagePath)) + ), + serverRoot + ) + ); + const resultData = await imageService.transform(fileData, { ...options, src: originalImagePath }); const finalFileURL = new URL('.' + filepath, clientRoot); const finalFolderURL = new URL('./', finalFileURL); diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 638fa91499d7..b42d71487410 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -167,16 +167,12 @@ export default function assets({ } filePath = prependForwardSlash( - joinPaths( - settings.config.base, - settings.config.build.assets, - propsToFilename(options) - ) + joinPaths(settings.config.build.assets, propsToFilename(options)) ); globalThis.astroAsset.staticImages.set(options, filePath); } - return filePath; + return prependForwardSlash(joinPaths(settings.config.base, filePath)); }; }, async buildEnd() { diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js index ccbd5b2f83ff..997c9c10d99d 100644 --- a/packages/astro/test/core-image.test.js +++ b/packages/astro/test/core-image.test.js @@ -292,6 +292,59 @@ describe('astro:image', () => { }); }); + describe('support base option correctly', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/core-image-base/', + experimental: { + assets: true, + }, + base: '/blog', + }); + await fixture.build(); + }); + + it('has base path prefix when using the Image component', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + const src = $('#local img').attr('src'); + expect(src.length).to.be.greaterThan(0); + expect(src.startsWith('/blog')).to.be.true; + }); + + it('has base path prefix when using getImage', async () => { + const html = await fixture.readFile('/get-image/index.html'); + const $ = cheerio.load(html); + const src = $('img').attr('src'); + expect(src.length).to.be.greaterThan(0); + expect(src.startsWith('/blog')).to.be.true; + }); + + it('has base path prefix when using image directly', async () => { + const html = await fixture.readFile('/direct/index.html'); + const $ = cheerio.load(html); + const src = $('img').attr('src'); + expect(src.length).to.be.greaterThan(0); + expect(src.startsWith('/blog')).to.be.true; + }); + + it('has base path prefix in Markdown', async () => { + const html = await fixture.readFile('/post/index.html'); + const $ = cheerio.load(html); + const src = $('img').attr('src'); + expect(src.length).to.be.greaterThan(0); + expect(src.startsWith('/blog')).to.be.true; + }); + + it('has base path prefix in Content Collection frontmatter', async () => { + const html = await fixture.readFile('/blog/one/index.html'); + const $ = cheerio.load(html); + const src = $('img').attr('src'); + expect(src.length).to.be.greaterThan(0); + expect(src.startsWith('/blog')).to.be.true; + }); + }); + describe('build ssg', () => { before(async () => { fixture = await loadFixture({ diff --git a/packages/astro/test/fixtures/core-image-base/package.json b/packages/astro/test/fixtures/core-image-base/package.json new file mode 100644 index 000000000000..5400b7028966 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/package.json @@ -0,0 +1,11 @@ +{ + "name": "@test/core-image-ssg", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + }, + "exports": { + "./service": "./src/service.ts" + } +} diff --git a/packages/astro/test/fixtures/core-image-base/src/assets/penguin1.jpg b/packages/astro/test/fixtures/core-image-base/src/assets/penguin1.jpg new file mode 100644 index 000000000000..6c5dcd37a30a Binary files /dev/null and b/packages/astro/test/fixtures/core-image-base/src/assets/penguin1.jpg differ diff --git a/packages/astro/test/fixtures/core-image-base/src/assets/penguin2.jpg b/packages/astro/test/fixtures/core-image-base/src/assets/penguin2.jpg new file mode 100644 index 000000000000..db6c44709142 Binary files /dev/null and b/packages/astro/test/fixtures/core-image-base/src/assets/penguin2.jpg differ diff --git a/packages/astro/test/fixtures/core-image-base/src/content/blog/one.md b/packages/astro/test/fixtures/core-image-base/src/content/blog/one.md new file mode 100644 index 000000000000..59a5b77baf03 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/content/blog/one.md @@ -0,0 +1,10 @@ +--- +title: One +image: ~/assets/penguin2.jpg +cover: + image: ../../assets/penguin1.jpg +--- + +# A post + +text here diff --git a/packages/astro/test/fixtures/core-image-base/src/content/config.ts b/packages/astro/test/fixtures/core-image-base/src/content/config.ts new file mode 100644 index 000000000000..b38ad070e100 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/content/config.ts @@ -0,0 +1,15 @@ +import { defineCollection, image, z } from "astro:content"; + +const blogCollection = defineCollection({ + schema: z.object({ + title: z.string(), + image: image(), + cover: z.object({ + image: image() + }) + }), +}); + +export const collections = { + blog: blogCollection +}; diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/alias.astro b/packages/astro/test/fixtures/core-image-base/src/pages/alias.astro new file mode 100644 index 000000000000..10990dbe3e9b --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/alias.astro @@ -0,0 +1,5 @@ +--- +import image from "~/assets/penguin1.jpg"; +--- + +A penguin! diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/aliasMarkdown.md b/packages/astro/test/fixtures/core-image-base/src/pages/aliasMarkdown.md new file mode 100644 index 000000000000..048a79bdd5cf --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/aliasMarkdown.md @@ -0,0 +1,3 @@ +![A penguin](~/assets/penguin1.jpg) + +A penguin diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/blog/[...slug].astro b/packages/astro/test/fixtures/core-image-base/src/pages/blog/[...slug].astro new file mode 100644 index 000000000000..dc25493e854a --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/blog/[...slug].astro @@ -0,0 +1,33 @@ +--- +import { getImage } from 'astro:assets'; +import { getCollection } from 'astro:content'; + +export async function getStaticPaths() { + const blogEntries = await getCollection('blog'); + return blogEntries.map(entry => ({ + params: { slug: entry.slug }, props: { entry }, + })); +} + +const { entry } = Astro.props; +const { Content } = await entry.render(); +const myImage = await getImage(entry.data.image); +--- + + + Testing + + +

Testing

+ +
+ +
+ +
+ +
+ + + + diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/direct.astro b/packages/astro/test/fixtures/core-image-base/src/pages/direct.astro new file mode 100644 index 000000000000..10990dbe3e9b --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/direct.astro @@ -0,0 +1,5 @@ +--- +import image from "~/assets/penguin1.jpg"; +--- + +A penguin! diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/format.astro b/packages/astro/test/fixtures/core-image-base/src/pages/format.astro new file mode 100644 index 000000000000..d2b165d892b5 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/format.astro @@ -0,0 +1,18 @@ +--- +import { Image } from 'astro:assets'; +import myImage from "../assets/penguin1.jpg"; +--- + + + + + +
+ a penguin +
+ +
+ a penguin +
+ + diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/get-image.astro b/packages/astro/test/fixtures/core-image-base/src/pages/get-image.astro new file mode 100644 index 000000000000..d83b1fd8ee78 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/get-image.astro @@ -0,0 +1,8 @@ +--- +import { getImage } from "astro:assets"; +import image from "../assets/penguin2.jpg"; + +const myImage = await getImage({ src: image, width: 207, height: 243, alt: 'a penguin' }); +--- + + diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/index.astro b/packages/astro/test/fixtures/core-image-base/src/pages/index.astro new file mode 100644 index 000000000000..d7f9b05519a5 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/index.astro @@ -0,0 +1,18 @@ +--- +import { Image } from 'astro:assets'; +import myImage from "../assets/penguin1.jpg"; +--- + + + + + +
+ a penguin +
+ +
+ fred +
+ + diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/post.md b/packages/astro/test/fixtures/core-image-base/src/pages/post.md new file mode 100644 index 000000000000..98da01ce41b2 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/post.md @@ -0,0 +1,3 @@ +![My article cover](../assets/penguin1.jpg) + +Image worked diff --git a/packages/astro/test/fixtures/core-image-base/src/pages/quality.astro b/packages/astro/test/fixtures/core-image-base/src/pages/quality.astro new file mode 100644 index 000000000000..706bb6766934 --- /dev/null +++ b/packages/astro/test/fixtures/core-image-base/src/pages/quality.astro @@ -0,0 +1,22 @@ +--- +import { Image } from 'astro:assets'; +import myImage from "../assets/penguin1.jpg"; +--- + + + + + +
+ a penguin +
+ +
+ a penguin +
+ +
+ a penguin +
+ + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 046e984bc940..c81b8f4ba678 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1869,6 +1869,12 @@ importers: dependencies: astro: link:../../.. + packages/astro/test/fixtures/core-image-base: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + packages/astro/test/fixtures/core-image-ssg: specifiers: astro: workspace:*