diff --git a/packages/docusaurus-mdx-loader/src/loader.ts b/packages/docusaurus-mdx-loader/src/loader.ts index 380a1b2a8e..7a7f63c630 100644 --- a/packages/docusaurus-mdx-loader/src/loader.ts +++ b/packages/docusaurus-mdx-loader/src/loader.ts @@ -7,6 +7,7 @@ import logger from '@docusaurus/logger'; import { + aliasedSitePath, DEFAULT_PARSE_FRONT_MATTER, getFileLoaderUtils, getWebpackLoaderCompilerName, @@ -16,7 +17,6 @@ import { compileToJSX, createAssetsExportCode, extractContentTitleData, - readMetadataPath, } from './utils'; import type { SimpleProcessors, @@ -35,12 +35,6 @@ 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 & { markdownConfig: MarkdownConfig; staticDirs: string[]; @@ -48,13 +42,10 @@ export type Options = Partial & { 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; @@ -112,40 +103,16 @@ ${JSON.stringify(frontMatter, null, 2)}`; } } - async function loadMetadata(): Promise { + 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'); @@ -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, + )}'` : '' } ${ diff --git a/packages/docusaurus-mdx-loader/src/utils.ts b/packages/docusaurus-mdx-loader/src/utils.ts index 90b8e77a71..36c74322fb 100644 --- a/packages/docusaurus-mdx-loader/src/utils.ts +++ b/packages/docusaurus-mdx-loader/src/utils.ts @@ -5,7 +5,6 @@ * 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'; @@ -13,23 +12,6 @@ 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 { - 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 diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 0f7e4b3dcd..bacaaad451 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -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, @@ -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, { diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index ffa4ac5311..7470183186 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -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, }), diff --git a/packages/docusaurus-plugin-content-pages/src/contentHelpers.ts b/packages/docusaurus-plugin-content-pages/src/contentHelpers.ts deleted file mode 100644 index 766cab0b51..0000000000 --- a/packages/docusaurus-plugin-content-pages/src/contentHelpers.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import type {LoadedContent, Metadata} from '@docusaurus/plugin-content-pages'; - -function indexPagesBySource(content: LoadedContent): Map { - return new Map(content.map((page) => [page.source, page])); -} - -// TODO this is bad, we should have a better way to do this (new lifecycle?) -// The source to page/permalink is a mutable map passed to the mdx loader -// See https://github.com/facebook/docusaurus/pull/10457 -// See https://github.com/facebook/docusaurus/pull/10185 -export function createContentHelpers() { - const sourceToPage = new Map(); - // const sourceToPermalink = new Map(); - - // Mutable map update :/ - function updateContent(content: LoadedContent): void { - sourceToPage.clear(); - // sourceToPermalink.clear(); - indexPagesBySource(content).forEach((value, key) => { - sourceToPage.set(key, value); - // sourceToPermalink.set(key, value.metadata.permalink); - }); - } - - return {updateContent, sourceToPage}; -} diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index d9f6b2ff8c..e4e0e6bd8f 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -24,7 +24,6 @@ import { getContentPathList, loadPagesContent, } from './content'; -import {createContentHelpers} from './contentHelpers'; import type {LoadContext, Plugin} from '@docusaurus/types'; import type { PluginOptions, @@ -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 { const { admonitions, @@ -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, }), @@ -125,7 +113,6 @@ export default async function pluginContentPages( if (!content) { return; } - contentHelpers.updateContent(content); await createAllRoutes({content, options, actions}); },