feat(mdx): add siteConfig.markdown.format to configure the default content parser (MDX / CommonMark) (#9097)

This commit is contained in:
Sébastien Lorber 2023-06-23 18:15:05 +02:00 committed by GitHub
parent be4e67caa9
commit cc6d9696f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 304 additions and 83 deletions

View file

@ -9,44 +9,126 @@ import {getFormat} from '../format';
describe('getFormat', () => {
it('uses frontMatter format over anything else', () => {
expect(getFormat({frontMatterFormat: 'md', filePath: 'xyz.md'})).toBe('md');
expect(getFormat({frontMatterFormat: 'md', filePath: 'xyz.mdx'})).toBe(
'md',
);
expect(getFormat({frontMatterFormat: 'mdx', filePath: 'xyz.md'})).toBe(
'mdx',
);
expect(getFormat({frontMatterFormat: 'mdx', filePath: 'xyz.mdx'})).toBe(
'mdx',
);
expect(
getFormat({
frontMatterFormat: 'md',
filePath: 'xyz.md',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(
getFormat({
frontMatterFormat: 'md',
filePath: 'xyz.mdx',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(
getFormat({
frontMatterFormat: 'mdx',
filePath: 'xyz.md',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
expect(
getFormat({
frontMatterFormat: 'mdx',
filePath: 'xyz.mdx',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
});
it('detects appropriate format from file extension', () => {
expect(getFormat({frontMatterFormat: 'detect', filePath: 'xyz.md'})).toBe(
'md',
);
it('supports "detects" for front matter', () => {
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'xyz.markdown'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'xyz.md',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(
getFormat({
frontMatterFormat: 'detect',
filePath: 'xyz.markdown',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'folder/xyz.md'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'folder/xyz.md',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'folder/xyz.markdown'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'folder/xyz.markdown',
markdownConfigFormat: 'mdx',
}),
).toBe('md');
expect(getFormat({frontMatterFormat: 'detect', filePath: 'xyz.mdx'})).toBe(
'mdx',
);
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'folder/xyz.mdx'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'xyz.mdx',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
expect(
getFormat({
frontMatterFormat: 'detect',
filePath: 'folder/xyz.mdx',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'xyz.unknown'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'xyz.unknown',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
expect(
getFormat({frontMatterFormat: 'detect', filePath: 'folder/xyz.unknown'}),
getFormat({
frontMatterFormat: 'detect',
filePath: 'folder/xyz.unknown',
markdownConfigFormat: 'md',
}),
).toBe('mdx');
});
it('fallbacks to markdown config format when front matter undefined', () => {
expect(
getFormat({
frontMatterFormat: undefined,
filePath: 'xyz.md',
markdownConfigFormat: 'mdx',
}),
).toBe('mdx');
expect(
getFormat({
frontMatterFormat: undefined,
filePath: 'xyz.mdx',
markdownConfigFormat: 'md',
}),
).toBe('md');
expect(
getFormat({
frontMatterFormat: undefined,
filePath: 'xyz.md',
markdownConfigFormat: 'detect',
}),
).toBe('md');
expect(
getFormat({
frontMatterFormat: undefined,
filePath: 'xyz.mdx',
markdownConfigFormat: 'detect',
}),
).toBe('mdx');
});
});

View file

@ -85,9 +85,18 @@ describe('MDX front matter schema', () => {
describe('validateDocFrontMatter format', () => {
testField({
prefix: 'format',
validFrontMatters: [{format: 'md'}, {format: 'mdx'}],
validFrontMatters: [
{},
{format: undefined},
{format: 'detect'},
{format: 'md'},
{format: 'mdx'},
],
invalidFrontMatters: [
[{format: 'xdm'}, '"format" must be one of [md, mdx, detect]'],
[{format: ''}, '"format" must be one of [md, mdx, detect]'],
[{format: null}, '"format" must be one of [md, mdx, detect]'],
[{unknownAttribute: 'mdx'}, '"unknownAttribute" is not allowed'],
],
});
});

View file

@ -7,6 +7,7 @@
import path from 'path';
import type {MDXFrontMatter} from './frontMatter';
import type {Format, FormatInput} from './index';
// Copied from https://mdxjs.com/packages/mdx/#optionsmdextensions
// Although we are likely to only use .md / .mdx anyway...
@ -21,20 +22,29 @@ const mdFormatExtensions = [
'.ron',
];
function isMDFormat(filepath: string) {
return mdFormatExtensions.includes(path.extname(filepath));
function getExtensionFormat(filepath: string): Format {
const isMDFormat = mdFormatExtensions.includes(path.extname(filepath));
// Bias toward mdx if unknown extension
return isMDFormat ? 'md' : 'mdx';
}
export function getFormat({
filePath,
frontMatterFormat,
markdownConfigFormat,
}: {
filePath: string;
frontMatterFormat: MDXFrontMatter['format'];
}): 'md' | 'mdx' {
if (frontMatterFormat !== 'detect') {
return frontMatterFormat;
markdownConfigFormat: FormatInput;
}): Format {
if (frontMatterFormat) {
if (frontMatterFormat !== 'detect') {
return frontMatterFormat;
}
return getExtensionFormat(filePath);
}
// Bias toward mdx if unknown extension
return isMDFormat(filePath) ? 'md' : 'mdx';
if (markdownConfigFormat !== 'detect') {
return markdownConfigFormat;
}
return getExtensionFormat(filePath);
}

View file

@ -10,18 +10,18 @@ import {
validateFrontMatter,
} from '@docusaurus/utils-validation';
import type {FormatInput} from './index';
export type MDXFrontMatter = {
format: 'md' | 'mdx' | 'detect';
format?: FormatInput;
};
export const DefaultMDXFrontMatter: MDXFrontMatter = {
format: 'detect',
format: undefined,
};
const MDXFrontMatterSchema = Joi.object<MDXFrontMatter>({
format: Joi.string()
.equal('md', 'mdx', 'detect')
.default(DefaultMDXFrontMatter.format),
format: Joi.string().equal('md', 'mdx', 'detect').optional(),
}).default(DefaultMDXFrontMatter);
export function validateMDXFrontMatter(frontMatter: unknown): MDXFrontMatter {

View file

@ -13,6 +13,10 @@ export default mdxLoader;
export type TOCItem = TOCItemImported;
export type Format = 'md' | 'mdx';
export type FormatInput = Format | 'detect';
export type LoadedMDXContent<FrontMatter, Metadata, Assets = undefined> = {
/** As verbatim declared in the MDX document. */
readonly frontMatter: FrontMatter;

View file

@ -235,6 +235,7 @@ export async function createProcessorCached({
const format = getFormat({
filePath,
frontMatterFormat: mdxFrontMatter.format,
markdownConfigFormat: reqOptions.markdownConfig.format,
});
return format === 'md' ? compilers.mdProcessor : compilers.mdxProcessor;