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

feat: handle simple mdx rendering #11633

Merged
merged 21 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
address feedback
  • Loading branch information
ematipico committed Aug 7, 2024
commit aeed67a4f7b6231a92ed924acc8af7cbcd7c9b27
11 changes: 9 additions & 2 deletions packages/astro/src/content/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ export const VIRTUAL_MODULE_ID = 'astro:content';
export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
export const DATA_STORE_VIRTUAL_ID = 'astro:data-layer-content';
export const RESOLVED_DATA_STORE_VIRTUAL_ID = '\0' + DATA_STORE_VIRTUAL_ID;
export const MODULES_IMPORTS_ID = 'astro:content-module-imports';
export const MODULES_IMPORTS_VIRTUAL_ID = '\0' + MODULES_IMPORTS_ID;

// Used by the content layer to create a virtual module that loads the `modules.mjs`, a file created by the content layer
// to map modules that are renderer at runtime
export const MODULES_MJS_ID = 'astro:content-module-imports';
export const MODULES_MJS_VIRTUAL_ID = '\0' + MODULES_MJS_ID;

export const DEFERRED_MODULE = 'astro:content-layer-deferred-module';

// Used by the content layer to create a virtual module that loads the `assets.mjs`
export const ASSET_IMPORTS_VIRTUAL_ID = 'astro:asset-imports';
export const ASSET_IMPORTS_RESOLVED_STUB_ID = '\0' + ASSET_IMPORTS_VIRTUAL_ID;
export const LINKS_PLACEHOLDER = '@@ASTRO-LINKS@@';
Expand Down
26 changes: 14 additions & 12 deletions packages/astro/src/content/data-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { MarkdownHeading } from '@astrojs/markdown-remark';
import * as devalue from 'devalue';
import { imageSrcToImportId, importIdToSymbolName } from '../assets/utils/resolveImports.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { CONTENT_MODULE_FLAG } from './consts.js';
import {DEFERRED_MODULE} from './consts.js';

const SAVE_DEBOUNCE_MS = 500;

Expand Down Expand Up @@ -36,9 +36,9 @@ export interface DataEntry<TData extends Record<string, unknown> = Record<string
/** The rendered content of the entry, if applicable. */
rendered?: RenderedContent;
/**
* If an entry is a module, its rendering phase is delegated to a virtual module during the runtime phase.
* If an entry is a deferred, its rendering phase is delegated to a virtual module during the runtime phase when calling `renderEntry`.
*/
isModule?: boolean;
isDeferred?: boolean;
ematipico marked this conversation as resolved.
Show resolved Hide resolved
}

export class DataStore {
Expand Down Expand Up @@ -140,8 +140,7 @@ export class DataStore {
}

addModuleImport(fileName: string, specifier: string) {
// TODO change resolution function
const id = contentModuleToId(specifier, fileName);
const id = contentModuleToId(fileName, specifier);
if (id) {
this.#moduleImports.set(fileName, id);
// We debounce the writes to disk because addAssetImport is called for every image in every file,
Expand Down Expand Up @@ -279,7 +278,7 @@ export default new Map([\n${lines.join(',\n')}]);
entries: () => this.entries(collectionName),
values: () => this.values(collectionName),
keys: () => this.keys(collectionName),
set: ({ id: key, data, body, filePath, isModule, digest, rendered }) => {
set: ({ id: key, data, body, filePath, isDeferred, digest, rendered }) => {
if (!key) {
throw new Error(`ID must be a non-empty string`);
}
Expand Down Expand Up @@ -311,8 +310,8 @@ export default new Map([\n${lines.join(',\n')}]);
if (rendered) {
entry.rendered = rendered;
}
if (isModule) {
entry.isModule = isModule;
if (isDeferred) {
entry.isDeferred = isDeferred;
}
this.set(collectionName, id, entry);
return true;
Expand Down Expand Up @@ -417,7 +416,10 @@ export interface ScopedDataStore {
digest?: number | string;
/** The rendered content, if applicable. */
rendered?: RenderedContent;
isModule?: boolean;
/**
* If an entry is a deferred, its rendering phase is delegated to a virtual module during the runtime phase.
*/
isDeferred?: boolean;
}) => boolean;
values: () => Array<DataEntry>;
keys: () => Array<string>;
Expand Down Expand Up @@ -469,10 +471,10 @@ function dataStoreSingleton() {
}

// TODO: find a better place to put this image
export function contentModuleToId(specifier: string, filePath: string) {
export function contentModuleToId(fileName: string, specifier: string) {
ematipico marked this conversation as resolved.
Show resolved Hide resolved
const params = new URLSearchParams(specifier);
params.set('importer', filePath);
params.set(CONTENT_MODULE_FLAG, 'true');
params.set('importer', fileName);
params.set(DEFERRED_MODULE, 'true');
ematipico marked this conversation as resolved.
Show resolved Hide resolved
return `${specifier}?${params.toString()}`;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/content/loaders/glob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function glob(globOptions: GlobOptions): Loader {

if (existingEntry && existingEntry.digest === digest && existingEntry.filePath) {
if (entryType.extensions.includes('.mdx')) {
store.addModuleImport(existingEntry.filePath, 'astro:content-module-imports');
store.addModuleImport(existingEntry.filePath, 'astro:content-layer-deferred-module');
}

if (existingEntry.rendered?.metadata?.imagePaths?.length) {
Expand All @@ -130,8 +130,8 @@ export function glob(globOptions: GlobOptions): Loader {
});

if (entryType.extensions.includes('.mdx')) {
store.addModuleImport(relativePath, 'astro:content-module-imports');
store.set({ id, data: parsedData, body, filePath: relativePath, digest, isModule: true });
store.addModuleImport(relativePath, 'astro:content-layer-deferred-module');
store.set({ id, data: parsedData, body, filePath: relativePath, digest, isDeferred: true });
} else if (entryType.getRenderFunction) {
let render = renderFunctionByContentType.get(entryType);
if (!render) {
Expand Down
61 changes: 23 additions & 38 deletions packages/astro/src/content/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,44 +88,12 @@ export function createGetCollection({
const data = rawEntry.filePath
? updateImageReferencesInData(rawEntry.data, rawEntry.filePath, imageAssetMap)
: rawEntry.data;
let entry;
if (rawEntry.isModule === true) {
try {
// @ts-expect-error virtual module
const { default: contentModules } = await import('astro:content-module-imports');
const module = contentModules.get(rawEntry.filePath);
const resolvedComponent = await module();

entry = {
...rawEntry,
collection,
id: rawEntry.id,
slug: rawEntry.id,
body: rawEntry.body,
data: rawEntry.data,
async render() {
return {
Content: resolvedComponent.Content,
rendered: {
metadata: {
headings: resolvedComponent.getHeadings?.() ?? [],
remarkPluginFrontmatter: resolvedComponent.frontmatter ?? {},
}
}
};
},
};
} catch (e) {
console.log(e)
}

} else {
entry = {
...rawEntry,
data,
collection,
};
}

const entry = {
...rawEntry,
data,
collection,
};
if (hasFilter && !filter(entry)) {
continue;
}
Expand Down Expand Up @@ -477,6 +445,23 @@ export async function renderEntry(
return entry.render();
}

if (entry.isDeferred) {
// @ts-expect-error virtual module
const { default: contentModules } = await import('astro:content-module-imports');
const module = contentModules.get(entry.filePath);
const resolvedComponent = await module();

return {
Content: resolvedComponent.Content,
rendered: {
metadata: {
headings: resolvedComponent.getHeadings?.() ?? [],
remarkPluginFrontmatter: resolvedComponent.frontmatter ?? {},
},
},
};
}

const html =
entry?.rendered?.metadata?.imagePaths?.length && entry.filePath
? await updateImageReferencesInBody(entry.rendered.html, entry.filePath)
Expand Down
9 changes: 4 additions & 5 deletions packages/astro/src/content/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { isYAMLException } from '../core/errors/utils.js';
import type { Logger } from '../core/logger/core.js';
import {
CONTENT_FLAGS,
CONTENT_LAYER_TYPE, CONTENT_MODULE_FLAG,
CONTENT_LAYER_TYPE,
DEFERRED_MODULE,
IMAGE_IMPORT_PREFIX,
PROPAGATED_ASSET_FLAG,
} from './consts.js';
Expand Down Expand Up @@ -474,11 +475,9 @@ export function hasContentFlag(viteId: string, flag: (typeof CONTENT_FLAGS)[numb
return flags.has(flag);
}

export function hasContentModuleFlag(
viteId: string,
): boolean {
export function isDeferredModule(viteId: string): boolean {
const flags = new URLSearchParams(viteId.split('?')[1] ?? '');
return flags.has(CONTENT_MODULE_FLAG);
return flags.has(DEFERRED_MODULE);
}

async function loadContentConfig({
Expand Down
25 changes: 12 additions & 13 deletions packages/astro/src/content/vite-plugin-content-virtual-mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import {
DATA_STORE_FILE,
DATA_STORE_VIRTUAL_ID,
MODULES_IMPORTS_FILE,
MODULES_IMPORTS_ID,
MODULES_IMPORTS_VIRTUAL_ID,
MODULES_MJS_ID,
MODULES_MJS_VIRTUAL_ID,
RESOLVED_DATA_STORE_VIRTUAL_ID,
RESOLVED_VIRTUAL_MODULE_ID,
VIRTUAL_MODULE_ID,
Expand All @@ -40,7 +40,7 @@ import {
getEntrySlug,
getEntryType,
getExtGlob,
hasContentModuleFlag,
isDeferredModule,
} from './utils.js';

interface AstroContentVirtualModPluginParams {
Expand All @@ -61,7 +61,7 @@ export function astroContentVirtualModPlugin({
configResolved(config) {
IS_DEV = config.mode === 'development';
},
async resolveId(id, importer) {
async resolveId(id) {
if (id === VIRTUAL_MODULE_ID) {
if (!settings.config.experimental.contentCollectionCache) {
return RESOLVED_VIRTUAL_MODULE_ID;
Expand All @@ -77,28 +77,27 @@ export function astroContentVirtualModPlugin({
return RESOLVED_DATA_STORE_VIRTUAL_ID;
}

if (hasContentModuleFlag(id)) {
if (isDeferredModule(id)) {
const [, query] = id.split('?');
const params = new URLSearchParams(query);
const importerParam = params.get('importer');
const importerPath = importerParam
? fileURLToPath(new URL(importerParam, settings.config.root))
: importer;
let importerPath = undefined;
if (importerParam && URL.canParse(importerParam, settings.config.root.toString())) {
importerPath = fileURLToPath(new URL(importerParam, settings.config.root));
}
if (importerPath) {
return await this.resolve(importerPath);
}
}

if (id === MODULES_IMPORTS_ID) {
if (id === MODULES_MJS_ID) {
const modules = new URL(MODULES_IMPORTS_FILE, settings.dotAstroDir);
if (fs.existsSync(modules)) {
return fileURLToPath(modules);
}
return MODULES_IMPORTS_VIRTUAL_ID;
return MODULES_MJS_VIRTUAL_ID;
}



if (id === ASSET_IMPORTS_VIRTUAL_ID) {
const assetImportsFile = new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir);
if (fs.existsSync(assetImportsFile)) {
Expand Down Expand Up @@ -156,7 +155,7 @@ export function astroContentVirtualModPlugin({
return 'export default new Map()';
}

if (id === MODULES_IMPORTS_VIRTUAL_ID) {
if (id === MODULES_MJS_VIRTUAL_ID) {
return 'export default new Map()';
}
},
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/core/errors/errors-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,8 @@ export const ContentLayerWriteError = {
export const GetEntryDeprecationError = {
name: 'GetEntryDeprecationError',
title: 'Invalid use of `getDataEntryById` or `getEntryBySlug` function.',
message: (collection: string, method: string) => `The \`${method}\` function is deprecated and cannot be used to query the "${collection}" collection. Use \`getEntry\` instead.`,
message: (collection: string, method: string) =>
`The \`${method}\` function is deprecated and cannot be used to query the "${collection}" collection. Use \`getEntry\` instead.`,
hint: 'Use the `getEntry` or `getCollection` functions to query content layer collections.',
} satisfies ErrorData;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineCollection, z, reference } from 'astro:content';
import { file, glob } from 'astro/loaders';
import { glob } from 'astro/loaders';

const reptiles = defineCollection({
type: 'experimental_content',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const getStaticPaths = (async () => {
if(!collection) return []
return collection.map((reptile) => ({
params: {
slug: `/${reptile.id}`
slug: `${reptile.id}`
},
props: {
reptile
Expand Down