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

语法高亮

本指南探讨了如何对代码块应用语法高亮。 MDX 支持标准 Markdown 语法(CommonMark)。 它默认不对代码块应用语法高亮。

有两种方式实现语法高亮:编译时或运行时。 在编译时进行意味着预先投入精力,这样读者将 有快速的体验,因为没有额外的代码发送给他们(语法高亮 需要大量代码才能工作)。 在运行时进行通过将工作转移到客户端提供更多灵活性。 但这可能导致读者体验缓慢。 它还取决于你使用的框架(即特定于 React、Preact、 Vue 等)

编译时语法高亮

例如使用 rehype-starry-nightstarry-night)、 rehype-highlightlowlighthighlight.js) 或 @mapbox/rehype-prismrefractorprism), 像这样:

example.js
import {compile} from '@mdx-js/mdx'
import rehypeStarryNight from 'rehype-starry-night'

const code = `~~~js
console.log(1)
~~~`

console.log(
  String(await compile(code, {rehypePlugins: [rehypeStarryNight]}))
)
(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 rehypeStarryNight(options?: Readonly<Options> | null | undefined): (tree: Root, file: VFile) => Promise<Root>
import rehypeStarryNight

Plugin to highlight code with starry-night.

  • @param options Configuration (optional).
  • @returns Transform.
const code: "~~~js\nconsole.log(1)\n~~~"
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
var String: StringConstructor
(value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

(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.
const code: "~~~js\nconsole.log(1)\n~~~"
(property) rehypePlugins?: PluggableList | null | undefined

List of rehype plugins (optional).

(alias) function rehypeStarryNight(options?: Readonly<Options> | null | undefined): (tree: Root, file: VFile) => Promise<Root>
import rehypeStarryNight

Plugin to highlight code with starry-night.

  • @param options Configuration (optional).
  • @returns Transform.
展开等价 JSX
output.jsx
<>
  <pre>
    <code className="language-js">
      <span className="pl-en">console</span>.<span className="pl-c1">log</span>(<span className="pl-c1">1</span>)
    </code>
  </pre>
</>

重要:你很可能还需要在页面上某处包含 CSS。 参见你正在使用的插件的文档获取更多信息。

运行时语法高亮

例如使用 react-syntax-highlighter, 像这样:

example.jsx
import SyntaxHighlighter from 'react-syntax-highlighter'
import Post from './example.mdx' // Assumes an integration is used to compile MDX -> JS.

console.log(<Post components={{code}} />)

function code({className, ...properties}) {
  const match = /language-(\w+)/.exec(className || '')
  return match
    ? <SyntaxHighlighter language={match[1]} PreTag="div" {...properties} />
    : <code className={className} {...properties} />
}
展开等价 JSX
output.jsx
<>
  <pre>
    <div
      className="language-js"
      style={{
        background: '#F0F0F0',
        color: '#444',
        display: 'block',
        overflowX: 'auto',
        padding: '0.5em'
      }}
    >
      <code style={{whiteSpace: 'pre'}}>
        <span>console.</span>
        <span style={{color: '#397300'}}>log</span>
        <span>(</span>
        <span style={{color: '#880000'}}>1</span>
        <span>)</span>
      </code>
    </div>
  </pre>
</>

使用 meta 字段进行语法高亮

Markdown 支持代码的 meta 字符串:

example.mdx
```js filename="index.js"
console.log(1)
```

meta 部分是语言(本例中为 js)之后的所有内容。 这是 Markdown 的一个隐藏部分:通常被忽略。 但如上例所示,它是放置一些额外字段的有用位置。

@mdx-js/mdx 不知道你是否将代码作为组件处理或 该 meta 字符串的格式是什么,所以它默认按 Markdown 的方式处理: meta 被忽略。

但如果你想在运行时访问 meta 呢? 这正是 rehype 插件 rehype-mdx-code-props 所做的。 它让你在 meta 部分输入 JSX 属性,你可以通过 pre 的组件来访问。

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

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