跳转到导航
1-2 分钟阅读
作者:Titus Wormer

Frontmatter

本指南探讨了如何在 MDX 中支持 YAML frontmatter。 MDX 支持标准 Markdown 语法(CommonMark)。 这意味着 frontmatter 默认不受支持。

MDX 提供了一个强大且动态的 frontmatter 替代方案,即 ESM (import/export)。 这些导出:

example.mdx
export const name = 'World'
export const title = 'Hi, ' + name + '!'

# {title}

可以这样使用:

example.js
import * as Post from './example.mdx' // Assumes an integration is used to compile MDX -> JS.

console.log(Post.title) // Prints 'Hi, World!'
(alias) module "*.mdx"
import Post

An MDX file which exports a JSX component.

The default export of MDX files is a function which takes props and returns a JSX element. MDX files can export other identifiers from within the MDX file as well, either authored manually or automatically through plugins

It’s currently not possible for the other exports to be typed automatically. You can type them yourself with a TypeScript script which augments *.mdx modules. A script file is a file which doesn’t use top-level ESM syntax, but ESM syntax is allowed inside the declared module.

This is typically useful for exports created by plugins. For example:

// mdx-custom.d.ts
declare module '*.mdx' {
  import { Frontmatter } from 'my-frontmatter-types';

  export const frontmatter: Frontmatter;
  export const title: string;
}

The previous example added types to all .mdx files. To define types for a specific MDX file, create a file with the same name but postfixed with .d.ts next to the MDX file.

For example, given the following MDX file my-component.mdx:

export const message = 'world';

# Hello {message}

Create the following file named my-component.mdx.d.ts in the same directory:

export { default } from '*.mdx';

export const message: string;

Note that this overwrites the declare module '*.mdx' { … } types from earlier, which is why you also need to define the default export. You can also define your own default export type to narrow the accepted prop types of this specific file.

It should now be possible to import both the MDX component and the exported constant message.

namespace console
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

  • @since v0.1.100
(alias) module "*.mdx"
import Post

An MDX file which exports a JSX component.

The default export of MDX files is a function which takes props and returns a JSX element. MDX files can export other identifiers from within the MDX file as well, either authored manually or automatically through plugins

It’s currently not possible for the other exports to be typed automatically. You can type them yourself with a TypeScript script which augments *.mdx modules. A script file is a file which doesn’t use top-level ESM syntax, but ESM syntax is allowed inside the declared module.

This is typically useful for exports created by plugins. For example:

// mdx-custom.d.ts
declare module '*.mdx' {
  import { Frontmatter } from 'my-frontmatter-types';

  export const frontmatter: Frontmatter;
  export const title: string;
}

The previous example added types to all .mdx files. To define types for a specific MDX file, create a file with the same name but postfixed with .d.ts next to the MDX file.

For example, given the following MDX file my-component.mdx:

export const message = 'world';

# Hello {message}

Create the following file named my-component.mdx.d.ts in the same directory:

export { default } from '*.mdx';

export const message: string;

Note that this overwrites the declare module '*.mdx' { … } types from earlier, which is why you also need to define the default export. You can also define your own default export type to narrow the accepted prop types of this specific file.

It should now be possible to import both the MDX component and the exported constant message.

const title: string

不过你可能更喜欢 frontmatter,因为它允许你定义可以在编译之前从文件系统中提取的数据。 假设我们的带 frontmatter 的 MDX 看起来像这样:

example.mdx
---
title: Hi, World!
---

# Hi, World!

那么不编译或求值,元数据可以这样访问:

example.js
import {read} from 'to-vfile'
import {matter} from 'vfile-matter'

const file = await read('example.mdx')
matter(file)

console.log(file.data.matter)
(alias) function read(description: Compatible, options: BufferEncoding | ReadOptions | null | undefined, callback: Callback): undefined (+2 overloads)
import read
(alias) function matter(file: VFile, options?: Readonly<Options> | null | undefined): undefined
import matter

Parse the YAML front matter in a file and expose it as file.data.matter.

If no matter is found in the file, nothing happens, except that file.data.matter is set to an empty object ({}).

If the file value is an Uint8Array, assumes it is encoded in UTF-8.

  • @param file Virtual file.
  • @param options Configuration (optional).
  • @returns Nothing.
const file: VFile
(alias) read(description: Compatible, options?: BufferEncoding | ReadOptions | null | undefined): Promise<VFile> (+2 overloads)
import read
(alias) matter(file: VFile, options?: Readonly<Options> | null | undefined): undefined
import matter

Parse the YAML front matter in a file and expose it as file.data.matter.

If no matter is found in the file, nothing happens, except that file.data.matter is set to an empty object ({}).

If the file value is an Uint8Array, assumes it is encoded in UTF-8.

  • @param file Virtual file.
  • @param options Configuration (optional).
  • @returns Nothing.
const file: VFile
namespace console
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

  • @since v0.1.100
const file: VFile
(property) VFile.data: Data

Place to store custom info (default: {}).

It’s OK to store custom data directly on the file but moving it to data is recommended.

  • @type {Data}
unknown

我们的编译器 @mdx-js/mdx 默认不理解 YAML frontmatter,但 可以通过 remark 插件 remark-frontmatter 来启用:

example.js
import fs from 'node:fs/promises'
import {compile} from '@mdx-js/mdx'
import remarkFrontmatter from 'remark-frontmatter'

const file = await compile(await fs.readFile('example.mdx'), {
  remarkPlugins: [remarkFrontmatter]
})

console.log(file)
(alias) module "node:fs/promises"
import fs
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compile

Compile MDX to JS.

  • @param vfileCompatible MDX document to parse.
  • @param compileOptions Compile configuration (optional).
  • @return Promise to compiled file.
(alias) function remarkFrontmatter(options?: Options | null | undefined): undefined
import remarkFrontmatter

Add support for frontmatter.

Notes

Doesn’t parse the data inside them: create your own plugin to do that.

  • @param options Configuration (default: 'yaml').
  • @returns Nothing.
const file: VFile
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compile

Compile MDX to JS.

  • @param vfileCompatible MDX document to parse.
  • @param compileOptions Compile configuration (optional).
  • @return Promise to compiled file.
(alias) module "node:fs/promises"
import fs
function readFile(path: PathLike | fs.FileHandle, options?: ({
    encoding?: null | undefined;
    flag?: OpenMode | undefined;
} & EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable) | null): Promise<NonSharedBuffer> (+2 overloads)

Asynchronously reads the entire contents of a file.

If no encoding is specified (using options.encoding), the data is returned as a Buffer object. Otherwise, the data will be a string.

If options is a string, then it specifies the encoding.

When the path is a directory, the behavior of fsPromises.readFile() is platform-specific. On macOS, Linux, and Windows, the promise will be rejected with an error. On FreeBSD, a representation of the directory's contents will be returned.

An example of reading a package.json file located in the same directory of the running code:

import { readFile } from 'node:fs/promises';
try {
  const filePath = new URL('./package.json', import.meta.url);
  const contents = await readFile(filePath, { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}

It is possible to abort an ongoing readFile using an AbortSignal. If a request is aborted the promise returned is rejected with an AbortError:

import { readFile } from 'node:fs/promises';

try {
  const controller = new AbortController();
  const { signal } = controller;
  const promise = readFile(fileName, { signal });

  // Abort the request before the promise settles.
  controller.abort();

  await promise;
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
}

Aborting an ongoing request does not abort individual operating system requests but rather the internal buffering fs.readFile performs.

Any specified FileHandle has to support reading.

  • @since v10.0.0
  • @param path filename or FileHandle
  • @return Fulfills with the contents of the file.
(property) remarkPlugins?: PluggableList | null | undefined

List of remark plugins (optional).

(alias) function remarkFrontmatter(options?: Options | null | undefined): undefined
import remarkFrontmatter

Add support for frontmatter.

Notes

Doesn’t parse the data inside them: create your own plugin to do that.

  • @param options Configuration (default: 'yaml').
  • @returns Nothing.
namespace console
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

  • @since v0.1.100
const file: VFile

现在它"可以用了"。 frontmatter 不会像 Markdown 那样被渲染。 但嵌入在 frontmatter 中的数据不能从 MDX 内部访问。 如果我们也想要那个呢? 像这样:

example.mdx
---
title: Hi, World!
---

# {title}

这正是 remark 插件 remark-mdx-frontmatter 所做的。

该插件与所有 remark 插件一样,可以作为 ProcessorOptions 中的 remarkPlugins 传递。 有关插件的更多信息请参见§ 扩展 MDX

MDX 用 ❤️ 在阿姆斯特丹、博伊西和全球各地打造
本站不会跟踪你。
MIT © 2017-2026
项目在 GitHub
网站在 GitHub
更新订阅 RSS
赞助 OpenCollective