Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resolve content layer images without filePath set #11858

Merged
merged 2 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/rich-kings-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Correctly resolves content layer images when filePath is not set
6 changes: 4 additions & 2 deletions packages/astro/src/assets/utils/resolveImports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { VALID_INPUT_FORMATS } from '../consts.js';
* @param filePath The path to the file that contains the imagem relative to the site root
* @returns A module id of the image that can be rsolved by Vite, or undefined if it is not a local image
*/
export function imageSrcToImportId(imageSrc: string, filePath: string): string | undefined {
export function imageSrcToImportId(imageSrc: string, filePath?: string): string | undefined {
// If the import is coming from the data store it will have a special prefix to identify it
// as an image import. We remove this prefix so that we can resolve the image correctly.
imageSrc = removeBase(imageSrc, IMAGE_IMPORT_PREFIX);
Expand All @@ -32,7 +32,9 @@ export function imageSrcToImportId(imageSrc: string, filePath: string): string |
// importer and get the correct full path for the imported image.

const params = new URLSearchParams(CONTENT_IMAGE_FLAG);
params.set('importer', filePath);
if (filePath) {
params.set('importer', filePath);
}
return `${imageSrc}?${params.toString()}`;
}

Expand Down
19 changes: 8 additions & 11 deletions packages/astro/src/content/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ export function createGetCollection({

const result = [];
for (const rawEntry of store.values<DataEntry>(collection)) {
const data = rawEntry.filePath
? updateImageReferencesInData(rawEntry.data, rawEntry.filePath, imageAssetMap)
: rawEntry.data;
const data = updateImageReferencesInData(rawEntry.data, rawEntry.filePath, imageAssetMap);

const entry = {
...rawEntry,
Expand Down Expand Up @@ -303,11 +301,9 @@ export function createGetEntry({
return;
}

if (entry.filePath) {
// @ts-expect-error virtual module
const { default: imageAssetMap } = await import('astro:asset-imports');
entry.data = updateImageReferencesInData(entry.data, entry.filePath, imageAssetMap);
}
// @ts-expect-error virtual module
const { default: imageAssetMap } = await import('astro:asset-imports');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want you can type this in dev-only.d.ts that's at the root of the package

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah thanks. til

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why, but those types don't seem to be picked up in this file

entry.data = updateImageReferencesInData(entry.data, entry.filePath, imageAssetMap);
return {
...entry,
collection,
Expand Down Expand Up @@ -415,18 +411,19 @@ async function updateImageReferencesInBody(html: string, fileName: string) {

function updateImageReferencesInData<T extends Record<string, unknown>>(
data: T,
fileName: string,
imageAssetMap: Map<string, ImageMetadata>,
fileName?: string,
imageAssetMap?: Map<string, ImageMetadata>,
): T {
return new Traverse(data).map(function (ctx, val) {
if (typeof val === 'string' && val.startsWith(IMAGE_IMPORT_PREFIX)) {
const src = val.replace(IMAGE_IMPORT_PREFIX, '');

const id = imageSrcToImportId(src, fileName);
if (!id) {
ctx.update(src);
return;
}
const imported = imageAssetMap.get(id);
const imported = imageAssetMap?.get(id);
if (imported) {
ctx.update(imported);
} else {
Expand Down
10 changes: 9 additions & 1 deletion packages/astro/src/content/vite-plugin-content-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getAssetsPrefix } from '../assets/utils/getAssetsPrefix.js';
import type { BuildInternals } from '../core/build/internal.js';
import type { AstroBuildPlugin } from '../core/build/plugin.js';
import type { StaticBuildOptions } from '../core/build/types.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import type { ModuleLoader } from '../core/module-loader/loader.js';
import { createViteLoader } from '../core/module-loader/vite.js';
import { joinPaths, prependForwardSlash } from '../core/path.js';
Expand Down Expand Up @@ -42,7 +43,14 @@ export function astroContentAssetPropagationPlugin({
? fileURLToPath(new URL(importerParam, settings.config.root))
: importer;

return this.resolve(base, importerPath, { skipSelf: true, ...opts });
const resolved = this.resolve(base, importerPath, { skipSelf: true, ...opts });
if (!resolved) {
throw new AstroError({
...AstroErrorData.ImageNotFound,
message: AstroErrorData.ImageNotFound.message(base),
});
}
return resolved;
}
if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
const base = id.split('?')[0];
Expand Down
15 changes: 15 additions & 0 deletions packages/astro/test/content-layer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ describe('Content Layer', () => {
assert.ok(json.entryWithReference.data.publishedDate instanceof Date);
});

it('loads images in frontmatter', async () => {
assert.ok(json.entryWithReference.data.heroImage.src.startsWith('/_astro'));
assert.equal(json.entryWithReference.data.heroImage.format, 'jpg');
});

it('loads images from custom loaders', async () => {
assert.ok(json.images[0].data.image.src.startsWith('/_astro'));
assert.equal(json.images[0].data.image.format, 'jpg');
});

it('handles remote images in custom loaders', async () => {
console.log(json.images[1].data.image);
assert.ok(json.images[1].data.image.startsWith('https://'));
});

it('returns a referenced entry', async () => {
assert.ok(json.hasOwnProperty('referencedEntry'));
assert.deepEqual(json.referencedEntry, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ description: 'Learn about the Columbia NASA space shuttle.'
publishedDate: 'Sat May 21 2022 00:00:00 GMT-0400 (Eastern Daylight Time)'
tags: [space, 90s]
cat: tabby
heroImage: "./shuttle.jpg"
---

**Source:** [Wikipedia](https://en.wikipedia.org/wiki/Space_Shuttle_Endeavour)
Expand Down
19 changes: 18 additions & 1 deletion packages/astro/test/fixtures/content-layer/src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,23 @@ const numbers = defineCollection({
loader: glob({ pattern: 'src/data/glob-data/*', base: '.' }),
});

const images = defineCollection({
loader: () => [
{
id: '1',
image: '@images/shuttle.jpg'
},
{
id: '2',
image: 'https://images.unsplash.com/photo-1457364887197-9150188c107b?w=800&fm=jpg&fit=crop'
}
],
schema: ({image}) => z.object({
id: z.string(),
image: image()
})
});

const increment = defineCollection({
loader: {
name: 'increment-loader',
Expand All @@ -108,4 +125,4 @@ const increment = defineCollection({

});

export const collections = { blog, dogs, cats, numbers, spacecraft, increment };
export const collections = { blog, dogs, cats, numbers, spacecraft, increment, images };
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export async function GET() {

const increment = await getEntry('increment', 'value');

const images = await getCollection('images');

return new Response(
devalue.stringify({
customLoader,
Expand All @@ -25,6 +27,7 @@ export async function GET() {
entryWithReference,
referencedEntry,
increment,
images
})
);
}
Loading