0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-03 22:29:08 -05:00

Fix using optimized images with base (#6643)

* fix(images): Fix images having the wrong path when using `base`

* test(images): Add test for using images with base

* test: add more tests

* chore: changeset

* fix: paths

* refactor: feedback
This commit is contained in:
Erika 2023-03-27 15:50:02 +02:00 committed by GitHub
parent 25cd3e5749
commit fc0ed9c53c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 232 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix images not having the proper path when using `base`

View file

@ -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);

View file

@ -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() {

View file

@ -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({

View file

@ -0,0 +1,11 @@
{
"name": "@test/core-image-ssg",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
},
"exports": {
"./service": "./src/service.ts"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,10 @@
---
title: One
image: ~/assets/penguin2.jpg
cover:
image: ../../assets/penguin1.jpg
---
# A post
text here

View file

@ -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
};

View file

@ -0,0 +1,5 @@
---
import image from "~/assets/penguin1.jpg";
---
<img src={image.src} width={image.width} height={image.height} alt="A penguin!" />

View file

@ -0,0 +1,3 @@
![A penguin](~/assets/penguin1.jpg)
A penguin

View file

@ -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);
---
<html>
<head>
<title>Testing</title>
</head>
<body>
<h1>Testing</h1>
<div id="direct-image">
<img src={entry.data.image.src} width={entry.data.image.width} height={entry.data.image.height} />
</div>
<div id="nested-image">
<img src={entry.data.cover.image.src} width={entry.data.cover.image.width} height={entry.data.cover.image.height} />
</div>
<Content />
</body>
</html>

View file

@ -0,0 +1,5 @@
---
import image from "~/assets/penguin1.jpg";
---
<img src={image.src} width={image.width} height={image.height} alt="A penguin!" />

View file

@ -0,0 +1,18 @@
---
import { Image } from 'astro:assets';
import myImage from "../assets/penguin1.jpg";
---
<html>
<head>
</head>
<body>
<div id="no-format">
<Image src={myImage} alt="a penguin" />
</div>
<div id="format-avif">
<Image src={myImage} alt="a penguin" format="avif" />
</div>
</body>
</html>

View file

@ -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' });
---
<img src={myImage.src} {...myImage.attributes} />

View file

@ -0,0 +1,18 @@
---
import { Image } from 'astro:assets';
import myImage from "../assets/penguin1.jpg";
---
<html>
<head>
</head>
<body>
<div id="local">
<Image src={myImage} alt="a penguin" />
</div>
<div id="remote">
<Image src="https://avatars.githubusercontent.com/u/622227?s=64" alt="fred" width="48" height="48" />
</div>
</body>
</html>

View file

@ -0,0 +1,3 @@
![My article cover](../assets/penguin1.jpg)
Image worked

View file

@ -0,0 +1,22 @@
---
import { Image } from 'astro:assets';
import myImage from "../assets/penguin1.jpg";
---
<html>
<head>
</head>
<body>
<div id="no-quality">
<Image src={myImage} alt="a penguin" />
</div>
<div id="quality-low">
<Image src={myImage} alt="a penguin" quality="low" />
</div>
<div id="quality-num">
<Image src={myImage} alt="a penguin" quality="70" />
</div>
</body>
</html>

6
pnpm-lock.yaml generated
View file

@ -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:*