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

refactor(mdx-loader): re-export metadata module instead of serializing it #10470

Merged
merged 4 commits into from
Sep 2, 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
56 changes: 13 additions & 43 deletions packages/docusaurus-mdx-loader/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import logger from '@docusaurus/logger';
import {
aliasedSitePath,
DEFAULT_PARSE_FRONT_MATTER,
getFileLoaderUtils,
getWebpackLoaderCompilerName,
Expand All @@ -16,7 +17,6 @@ import {
compileToJSX,
createAssetsExportCode,
extractContentTitleData,
readMetadataPath,
} from './utils';
import type {
SimpleProcessors,
Expand All @@ -35,26 +35,17 @@ type Pluggable = any; // TODO fix this asap

export type MDXPlugin = Pluggable;

// This represents the path to the mdx metadata bundle path + its loaded content
export type LoadedMetadata = {
metadataPath: string;
metadataContent: unknown;
};

export type Options = Partial<MDXOptions> & {
markdownConfig: MarkdownConfig;
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
isMDXPartialFrontMatterWarningDisabled?: boolean;
removeContentTitle?: boolean;

// TODO Docusaurus v4: rename to just "metadata"?
// We kept retro-compatibility in v3 in case plugins/sites use mdx loader
metadataPath?: string | ((filePath: string) => string | LoadedMetadata);
metadataPath?: (filePath: string) => string;
createAssets?: (metadata: {
filePath: string;
frontMatter: {[key: string]: unknown};
metadata: unknown;
}) => {[key: string]: unknown};
resolveMarkdownLink?: ResolveMarkdownLink;

Expand Down Expand Up @@ -112,40 +103,16 @@ ${JSON.stringify(frontMatter, null, 2)}`;
}
}

async function loadMetadata(): Promise<LoadedMetadata | undefined> {
const metadataPath = (function getMetadataPath() {
if (!isMDXPartial) {
// Read metadata for this MDX and export it.
if (options.metadataPath && typeof options.metadataPath === 'function') {
const metadata = options.metadataPath(filePath);
if (!metadata) {
return undefined;
}
if (typeof metadata === 'string') {
return {
metadataPath: metadata,
metadataContent: await readMetadataPath(metadata),
};
}
if (!metadata.metadataPath) {
throw new Error(`Metadata path missing for file ${filePath}`);
}
if (!metadata.metadataContent) {
throw new Error(`Metadata content missing for file ${filePath}`);
}
return metadata;
}
return options.metadataPath?.(filePath);
}
return undefined;
}

const metadata = await loadMetadata();
if (metadata) {
this.addDependency(metadata.metadataPath);
}
})();

const assets =
options.createAssets && metadata
? options.createAssets({frontMatter, metadata: metadata.metadataContent})
options.createAssets && !isMDXPartial
? options.createAssets({filePath, frontMatter})
: undefined;

const fileLoaderUtils = getFileLoaderUtils(compilerName === 'server');
Expand All @@ -156,8 +123,11 @@ ${JSON.stringify(frontMatter, null, 2)}`;
export const frontMatter = ${stringifyObject(frontMatter)};
export const contentTitle = ${stringifyObject(contentTitle)};
${
metadata
? `export const metadata = ${JSON.stringify(metadata.metadataContent)};`
metadataPath
? `export {default as metadata} from '${aliasedSitePath(
metadataPath,
options.siteDir,
)}'`
: ''
}
${
Expand Down
18 changes: 0 additions & 18 deletions packages/docusaurus-mdx-loader/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/

import fs from 'fs-extra';
import logger from '@docusaurus/logger';
import {escapePath, type WebpackCompilerName} from '@docusaurus/utils';
import {getProcessor, type SimpleProcessorResult} from './processor';
import {validateMDXFrontMatter} from './frontMatter';
import preprocessor from './preprocessor';
import type {Options} from './loader';

/**
* When this throws, it generally means that there's no metadata file associated
* with this MDX document. It can happen when using MDX partials (usually
* starting with _). That's why it's important to provide the `isMDXPartial`
* function in config
*/
export async function readMetadataPath(metadataPath: string): Promise<unknown> {
try {
return await fs.readJSON(metadataPath, 'utf8');
} catch (error) {
throw new Error(
logger.interpolate`MDX loader can't read MDX metadata file path=${metadataPath}. Maybe the isMDXPartial option function was not provided?`,
{cause: error as Error},
);
}
}

/**
* Converts assets an object with Webpack require calls code.
* This is useful for mdx files to reference co-located assets using relative
Expand Down
41 changes: 16 additions & 25 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types';
import type {LoadContext, Plugin} from '@docusaurus/types';
import type {
PluginOptions,
BlogPostFrontMatter,
BlogPostMetadata,
Assets,
BlogTags,
BlogContent,
Expand Down Expand Up @@ -135,33 +133,26 @@ export default async function pluginContentBlog(
// Note that metadataPath must be the same/in-sync as
// the path from createData for each MDX.
const aliasedPath = aliasedSitePath(mdxPath, siteDir);
const metadataPath = path.join(
dataDir,
`${docuHash(aliasedPath)}.json`,
);
const metadataContent =
contentHelpers.sourceToBlogPost.get(aliasedPath)!.metadata;
return {
metadataPath,
metadataContent,
};
return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
},
// For blog posts a title in markdown is always removed
// Blog posts title are rendered separately
removeContentTitle: true,
// Assets allow to convert some relative images paths to
// require() calls
// @ts-expect-error: TODO fix typing issue
createAssets: ({
frontMatter,
metadata,
}: {
frontMatter: BlogPostFrontMatter;
metadata: BlogPostMetadata;
}): Assets => ({
image: frontMatter.image,
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
}),
// createAssets converts relative paths to require() calls
createAssets: ({filePath}: {filePath: string}): Assets => {
const blogPost = contentHelpers.sourceToBlogPost.get(
aliasedSitePath(filePath, siteDir),
)!;
if (!blogPost) {
throw new Error(`Blog post not found for filePath=${filePath}`);
}
return {
image: blogPost.metadata.frontMatter.image as string,
authorsImageUrls: blogPost.metadata.authors.map(
(author) => author.imageURL,
),
};
},
markdownConfig: siteConfig.markdown,
resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
const permalink = resolveMarkdownLinkPathname(linkPathname, {
Expand Down
13 changes: 2 additions & 11 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,9 @@ export default async function pluginContentDocs(
// Note that metadataPath must be the same/in-sync as
// the path from createData for each MDX.
const aliasedPath = aliasedSitePath(mdxPath, siteDir);
const metadataPath = path.join(
dataDir,
`${docuHash(aliasedPath)}.json`,
);
const metadataContent = contentHelpers.sourceToDoc.get(aliasedPath);
return {
metadataPath,
metadataContent,
};
return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
},
// Assets allow to convert some relative images paths to
// require(...) calls
// createAssets converts relative paths to require() calls
createAssets: ({frontMatter}: {frontMatter: DocFrontMatter}) => ({
image: frontMatter.image,
}),
Expand Down
33 changes: 0 additions & 33 deletions packages/docusaurus-plugin-content-pages/src/contentHelpers.ts

This file was deleted.

17 changes: 2 additions & 15 deletions packages/docusaurus-plugin-content-pages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
getContentPathList,
loadPagesContent,
} from './content';
import {createContentHelpers} from './contentHelpers';
import type {LoadContext, Plugin} from '@docusaurus/types';
import type {
PluginOptions,
Expand All @@ -47,8 +46,6 @@ export default async function pluginContentPages(
);
const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID);

const contentHelpers = createContentHelpers();

async function createPagesMDXLoaderRule(): Promise<RuleSetRule> {
const {
admonitions,
Expand Down Expand Up @@ -76,18 +73,9 @@ export default async function pluginContentPages(
// Note that metadataPath must be the same/in-sync as
// the path from createData for each MDX.
const aliasedSource = aliasedSitePath(mdxPath, siteDir);
const metadataPath = path.join(
dataDir,
`${docuHash(aliasedSource)}.json`,
);
const metadataContent = contentHelpers.sourceToPage.get(aliasedSource);
return {
metadataPath,
metadataContent,
};
return path.join(dataDir, `${docuHash(aliasedSource)}.json`);
},
// Assets allow to convert some relative images paths to
// require(...) calls
// createAssets converts relative paths to require() calls
createAssets: ({frontMatter}: {frontMatter: PageFrontMatter}) => ({
image: frontMatter.image,
}),
Expand Down Expand Up @@ -125,7 +113,6 @@ export default async function pluginContentPages(
if (!content) {
return;
}
contentHelpers.updateContent(content);
await createAllRoutes({content, options, actions});
},

Expand Down