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:
parent
25cd3e5749
commit
fc0ed9c53c
19 changed files with 232 additions and 8 deletions
5
.changeset/thick-penguins-turn.md
Normal file
5
.changeset/thick-penguins-turn.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix images not having the proper path when using `base`
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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({
|
||||
|
|
11
packages/astro/test/fixtures/core-image-base/package.json
vendored
Normal file
11
packages/astro/test/fixtures/core-image-base/package.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "@test/core-image-ssg",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*"
|
||||
},
|
||||
"exports": {
|
||||
"./service": "./src/service.ts"
|
||||
}
|
||||
}
|
BIN
packages/astro/test/fixtures/core-image-base/src/assets/penguin1.jpg
vendored
Normal file
BIN
packages/astro/test/fixtures/core-image-base/src/assets/penguin1.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
packages/astro/test/fixtures/core-image-base/src/assets/penguin2.jpg
vendored
Normal file
BIN
packages/astro/test/fixtures/core-image-base/src/assets/penguin2.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
10
packages/astro/test/fixtures/core-image-base/src/content/blog/one.md
vendored
Normal file
10
packages/astro/test/fixtures/core-image-base/src/content/blog/one.md
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: One
|
||||
image: ~/assets/penguin2.jpg
|
||||
cover:
|
||||
image: ../../assets/penguin1.jpg
|
||||
---
|
||||
|
||||
# A post
|
||||
|
||||
text here
|
15
packages/astro/test/fixtures/core-image-base/src/content/config.ts
vendored
Normal file
15
packages/astro/test/fixtures/core-image-base/src/content/config.ts
vendored
Normal 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
|
||||
};
|
5
packages/astro/test/fixtures/core-image-base/src/pages/alias.astro
vendored
Normal file
5
packages/astro/test/fixtures/core-image-base/src/pages/alias.astro
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
import image from "~/assets/penguin1.jpg";
|
||||
---
|
||||
|
||||
<img src={image.src} width={image.width} height={image.height} alt="A penguin!" />
|
3
packages/astro/test/fixtures/core-image-base/src/pages/aliasMarkdown.md
vendored
Normal file
3
packages/astro/test/fixtures/core-image-base/src/pages/aliasMarkdown.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
![A penguin](~/assets/penguin1.jpg)
|
||||
|
||||
A penguin
|
33
packages/astro/test/fixtures/core-image-base/src/pages/blog/[...slug].astro
vendored
Normal file
33
packages/astro/test/fixtures/core-image-base/src/pages/blog/[...slug].astro
vendored
Normal 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>
|
5
packages/astro/test/fixtures/core-image-base/src/pages/direct.astro
vendored
Normal file
5
packages/astro/test/fixtures/core-image-base/src/pages/direct.astro
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
import image from "~/assets/penguin1.jpg";
|
||||
---
|
||||
|
||||
<img src={image.src} width={image.width} height={image.height} alt="A penguin!" />
|
18
packages/astro/test/fixtures/core-image-base/src/pages/format.astro
vendored
Normal file
18
packages/astro/test/fixtures/core-image-base/src/pages/format.astro
vendored
Normal 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>
|
8
packages/astro/test/fixtures/core-image-base/src/pages/get-image.astro
vendored
Normal file
8
packages/astro/test/fixtures/core-image-base/src/pages/get-image.astro
vendored
Normal 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} />
|
18
packages/astro/test/fixtures/core-image-base/src/pages/index.astro
vendored
Normal file
18
packages/astro/test/fixtures/core-image-base/src/pages/index.astro
vendored
Normal 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>
|
3
packages/astro/test/fixtures/core-image-base/src/pages/post.md
vendored
Normal file
3
packages/astro/test/fixtures/core-image-base/src/pages/post.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
![My article cover](../assets/penguin1.jpg)
|
||||
|
||||
Image worked
|
22
packages/astro/test/fixtures/core-image-base/src/pages/quality.astro
vendored
Normal file
22
packages/astro/test/fixtures/core-image-base/src/pages/quality.astro
vendored
Normal 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
6
pnpm-lock.yaml
generated
|
@ -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:*
|
||||
|
|
Loading…
Add table
Reference in a new issue