in packages/docusaurus-mdx-loader/src/index.ts [120:244]
export default async function mdxLoader(
this: LoaderContext<Options>,
fileString: string,
): Promise<void> {
const callback = this.async();
const filePath = this.resourcePath;
const reqOptions = this.getOptions() ?? {};
const {frontMatter, content: contentWithTitle} = parseFrontMatter(fileString);
const {content, contentTitle} = parseMarkdownContentTitle(contentWithTitle, {
removeContentTitle: reqOptions.removeContentTitle,
});
const hasFrontMatter = Object.keys(frontMatter).length > 0;
if (!compilerCache.has(this.query)) {
const options: Options = {
...reqOptions,
remarkPlugins: [
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
...DEFAULT_OPTIONS.remarkPlugins,
[
transformImage,
{
staticDirs: reqOptions.staticDirs,
siteDir: reqOptions.siteDir,
},
],
[
transformLinks,
{
staticDirs: reqOptions.staticDirs,
siteDir: reqOptions.siteDir,
},
],
...(reqOptions.remarkPlugins ?? []),
],
rehypePlugins: [
...(reqOptions.beforeDefaultRehypePlugins ?? []),
...DEFAULT_OPTIONS.rehypePlugins,
...(reqOptions.rehypePlugins ?? []),
],
};
compilerCache.set(this.query, [createCompiler(options), options]);
}
const [compiler, options] = compilerCache.get(this.query)!;
let result: string;
try {
result = await compiler
.process({
contents: content,
path: this.resourcePath,
})
.then((res) => res.toString());
} catch (err) {
return callback(err as Error);
}
// MDX partials are MDX files starting with _ or in a folder starting with _
// Partial are not expected to have associated metadata files or front matter
const isMDXPartial = options.isMDXPartial?.(filePath);
if (isMDXPartial && hasFrontMatter) {
const errorMessage = `Docusaurus MDX partial files should not contain front matter.
Those partial files use the _ prefix as a convention by default, but this is configurable.
File at ${filePath} contains front matter that will be ignored:
${JSON.stringify(frontMatter, null, 2)}`;
if (!options.isMDXPartialFrontMatterWarningDisabled) {
const shouldError = process.env.NODE_ENV === 'test' || process.env.CI;
if (shouldError) {
return callback(new Error(errorMessage));
}
logger.warn(errorMessage);
}
}
function getMetadataPath(): string | undefined {
if (!isMDXPartial) {
// Read metadata for this MDX and export it.
if (options.metadataPath && typeof options.metadataPath === 'function') {
return options.metadataPath(filePath);
}
}
return undefined;
}
const metadataPath = getMetadataPath();
if (metadataPath) {
this.addDependency(metadataPath);
}
const metadataJsonString = metadataPath
? await readMetadataPath(metadataPath)
: undefined;
const metadata = metadataJsonString
? JSON.parse(metadataJsonString)
: undefined;
const assets =
reqOptions.createAssets && metadata
? reqOptions.createAssets({frontMatter, metadata})
: undefined;
const exportsCode = `
export const frontMatter = ${stringifyObject(frontMatter)};
export const contentTitle = ${stringifyObject(contentTitle)};
${metadataJsonString ? `export const metadata = ${metadataJsonString};` : ''}
${assets ? `export const assets = ${createAssetsExportCode(assets)};` : ''}
`;
const code = `
${pragma}
import React from 'react';
import { mdx } from '@mdx-js/react';
${exportsCode}
${result}
`;
return callback(null, code);
}