Skip to content

Commit

Permalink
Resolve images in the frontmatter relative to the current file (#6627)
Browse files Browse the repository at this point in the history
* feat(images): Resolve images in the frontmatter relative to the current file

* fix(images): Only recursively go through the object if it's not undefined

* fix(images): Add more safeguards

* test(images): Update content collections tests to be relative

* chore: changeset
  • Loading branch information
Princesseuh authored Mar 23, 2023
1 parent 0c8c5fc commit d338b6f
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-suns-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Update frontmatter assets to be relative to the current file instead of `src/assets`
6 changes: 3 additions & 3 deletions packages/astro/src/content/runtime-assets.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { pathToFileURL } from 'url';
import { z } from 'zod';
import { imageMetadata, type Metadata } from '../assets/utils/metadata.js';

Expand All @@ -7,9 +8,8 @@ export function createImage(options: { assetsDir: string; relAssetsDir: string }
throw new Error('Enable `experimental.assets` in your Astro config to use image()');
}

return z.string().transform(async (imagePath) => {
const fullPath = new URL(imagePath, options.assetsDir);
return await getImageMetadata(fullPath);
return z.string({ description: '__image' }).transform(async (imagePath) => {
return await getImageMetadata(pathToFileURL(imagePath));
});
};
}
Expand Down
38 changes: 35 additions & 3 deletions packages/astro/src/content/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import matter from 'gray-matter';
import fsMod from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import type { EmitFile } from 'rollup';
import { normalizePath, type ErrorPayload as ViteErrorPayload, type ViteDevServer } from 'vite';
import type { EmitFile, PluginContext } from 'rollup';
import { normalizePath, type ViteDevServer, type ErrorPayload as ViteErrorPayload } from 'vite';
import { z } from 'zod';
import type { AstroConfig, AstroSettings } from '../@types/astro.js';
import { emitESMImage } from '../assets/utils/emitAsset.js';
Expand Down Expand Up @@ -88,7 +88,8 @@ export function getEntrySlug({

export async function getEntryData(
entry: EntryInfo & { unvalidatedData: Record<string, unknown>; _internal: EntryInternal },
collectionConfig: CollectionConfig
collectionConfig: CollectionConfig,
resolver: (idToResolve: string) => ReturnType<PluginContext['resolve']>
) {
// Remove reserved `slug` field before parsing data
let { slug, ...data } = entry.unvalidatedData;
Expand Down Expand Up @@ -117,6 +118,37 @@ export async function getEntryData(
message: AstroErrorData.ContentSchemaContainsSlugError.message(entry.collection),
});
}

/**
* Resolve all the images referred to in the frontmatter from the file requesting them
*/
async function preprocessAssetPaths(object: Record<string, any>) {
if (typeof object !== 'object' || object === null) return;

for (let [schemaName, schema] of Object.entries<any>(object)) {
if (schema._def.description === '__image') {
object[schemaName] = z.preprocess(
async (value: unknown) => {
if (!value || typeof value !== 'string') return value;
return (await resolver(value))?.id;
},
schema,
{ description: undefined }
);
} else if ('shape' in schema) {
await preprocessAssetPaths(schema.shape);
} else if ('unwrap' in schema) {
const unwrapped = schema.unwrap().shape;

if (unwrapped) {
await preprocessAssetPaths(unwrapped);
}
}
}
}

await preprocessAssetPaths(collectionConfig.schema.shape);

// Use `safeParseAsync` to allow async transforms
const parsed = await collectionConfig.schema.safeParseAsync(entry.unvalidatedData, {
errorMap,
Expand Down
8 changes: 6 additions & 2 deletions packages/astro/src/content/vite-plugin-content-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import { AstroError } from '../core/errors/errors.js';
import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js';
import { CONTENT_FLAG } from './consts.js';
import {
NoCollectionError,
getContentEntryExts,
getContentPaths,
getEntryData,
getEntryInfo,
getEntrySlug,
getEntryType,
globalContentConfigObserver,
NoCollectionError,
patchAssets,
type ContentConfig,
} from './utils.js';
Expand Down Expand Up @@ -232,7 +232,11 @@ export const _internal = {

const collectionConfig = contentConfig?.collections[collection];
let data = collectionConfig
? await getEntryData({ id, collection, slug, _internal, unvalidatedData }, collectionConfig)
? await getEntryData(
{ id, collection, slug, _internal, unvalidatedData },
collectionConfig,
(idToResolve: string) => pluginContext.resolve(idToResolve, fileId)
)
: unvalidatedData;

await patchAssets(data, pluginContext.meta.watchMode, pluginContext.emitFile, settings);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: One
image: penguin2.jpg
image: ~/assets/penguin2.jpg
cover:
image: penguin1.jpg
image: ../../assets/penguin1.jpg
---

# A post
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: One
image: penguin2.jpg
image: ~/assets/penguin2.jpg
cover:
image: penguin1.jpg
image: ../../assets/penguin1.jpg
---

# A post
Expand Down

0 comments on commit d338b6f

Please sign in to comment.