Skip to navigation

语法高亮

¥Syntax highlighting

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

¥This guide explores how to apply syntax highlighting to code blocks. MDX supports standard markdown syntax (CommonMark). It does not apply syntax highlighting to code blocks by default.

有两种方法可以实现语法高亮:在编译时或运行时。在编译时执行此操作意味着预先花费精力,以便读者能够获得快速的体验,因为不会向他们发送额外的代码(语法高亮需要大量代码才能工作)。在运行时执行此操作可以将工作转移给客户端,从而提供更大的灵活性。但这可能会导致读者体验缓慢。它还取决于你使用的框架(例如特定于 React、Preact、Vue 等)

¥There are two ways to accomplish syntax highlighting: at compile time or at runtime. Doing it at compile time means the effort is spent upfront so that readers will have a fast experience as no extra code is sent to them (syntax highlighting needs a lot of code to work). Doing it at runtime gives more flexibility by moving the work to the client. This can result in a slow experience for readers though. It also depends on what framework you use (as in it’s specific to React, Preact, Vue, etc.)

编译时语法高亮

¥Syntax highlighting at compile time

例如,通过执行以下操作使用 rehype-starry-nightstarry-night)、rehype-highlightlowlighthighlight.js)或 @mapbox/rehype-prismrefractorprism):

¥Use for example rehype-starry-night (starry-night), rehype-highlight (lowlight, highlight.js), or @mapbox/rehype-prism (refractor, prism) by doing something like this:

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 calling require('console').

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.
Expand equivalent 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。有关更多信息,请参阅你正在使用的插件的文档。

¥Important: you must likely also include CSS somewhere on the page. See the documentation of the plugin you’re using for more information.

运行时语法高亮

¥Syntax highlighting at run time

例如使用 react-syntax-highlighter,执行如下操作:

¥Use for example react-syntax-highlighter, by doing something like this:

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} />
}
Expand equivalent 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 字段进行语法高亮显示

¥Syntax highlighting with the meta field

Markdown 支持代码的元字符串:

¥Markdown supports a meta string for code:

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

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

¥The meta part is everything after the language (in this case, js). This is a hidden part of markdown: it’s normally ignored. But as the above example shows, it’s a useful place to put some extra fields.

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

¥@mdx-js/mdx doesn’t know whether you’re handling code as a component or what the format of that meta string is, so it defaults to how markdown handles it: meta is ignored.

但是如果你想在运行时访问 meta 怎么办?这正是 rehype 插件 rehype-mdx-code-props 所做的。它允许你在 meta 部分中键入 JSX 属性,你可以使用 pre 的组件来访问该属性。

¥But what if you want to access meta at runtime? That’s exactly what the rehype plugin rehype-mdx-code-props does. It lets you type JSX attributes in the meta part which you can access by with a component for pre.

该插件与所有 rehype 插件一样,可以作为 rehypePluginsProcessorOptions 传递。有关插件的更多信息可在 § 扩展 MDX 中找到

¥That plugin, like all rehype plugins, can be passed as rehypePlugins in ProcessorOptions. More info on plugins is available in § Extending MDX

MDX 中文网 - 粤ICP备13048890号