概述

项目通过 remark / rehype 插件链,把标准 markdown 写法在解析时转换为已有组件的样式渲染,不需要在 .mdx 里 import 或写标签

适用范围:.md.mdx 文件。

底层实现:

  • src/utils/shiki-classify.js — shiki transformer,把代码块按 lang/meta 分类
  • src/utils/rehype-code-block-wrap.js — rehype 插件,给分类后的 <pre> 包 CodeBlock 组件 DOM
  • src/utils/remark-gfm-alert.js — remark 插件,把 > [!type] 引用解析为 Callout HTML

代码块

基础规则

``` 必标语言;命令和输出分两个块; 嵌套用 4 个反引号外层。

自动分类(按 lang 推断)

下面这个块写的是 bash 终端命令 — 不用任何标签,自动渲染为绿色 terminal:

TERMINALbash
$ ls -la
$ pwd
$ echo "hello"

下面是输出 — 用 textplaintext 标识,会渲染为带颜色但不高亮(因为是 code 蓝色,不是 log 红):

CODEtext
total 12
drwxr-xr-x 3 user user 4096 Jan 15 10:00 .
drwxr-xr-x 8 user user 4096 Jan 15 10:00 ..
-rw-r--r-- 1 user user  220 Jan 15 10:00 .bash_logout

下面是 Python 代码 — 不用任何标签,自动渲染为蓝色 code:

CODEpython
def hello(name: str) -> str:
    return f"Hello, {name}"

if __name__ == "__main__":
    print(hello("world"))

下面是 YAML 配置 — 自动渲染为紫色 config:

CONFIG
server:
  listen: 80
  server_name: example.com
  location /:
    proxy_pass: http://backend

下面是日志(用 log 语言) — 渲染为红色 log:

LOGERROR
2024-01-15 10:23:45 INFO  main.py:42  Service started
2024-01-15 10:24:12 ERROR main.py:88  Connection refused
2024-01-15 10:24:13 WARN  main.py:90  Retry attempt 1/3

下面是堆栈错误(用 error 语言) — 渲染为红色 log + level=error:

CODEplaintext
Traceback (most recent call last):
  File "main.py", line 42, in <module>
    connect()
ConnectionRefusedError: [Errno 111] Connection refused

分类规则总表

按 lang 推断(无 meta 标签时):

语言渲染为颜色
bash / shell / sh / zsh / powershell终端(terminal)绿
python / javascript / typescript / go / rust / java / c / cpp / astro / zig代码(code)
yaml / json / ini / toml / conf / xml配置(config)
nginx / dockerfile / sql / html / css / markdown代码(code)
log / console日志(log)
text / plaintext代码(code)
其他 / 未知代码(code)蓝(兜底)

meta 显式覆盖

``` 后加 meta 标签强制指定类型。

下面是网络设备配置示例(华为 VRP):

NETWORK
! 华为设备配置示例
sysname SW1
interface GigabitEthernet0/0/1
 port link-type access
 port default vlan 10
quit

下面是中间件配置示例(带 service-config meta):

CONFIG
server {
  listen 80;
  server_name example.com;
}
meta 标签类型颜色
cli / interactiveterminal绿
device-config / devicenetwork
service-config / middlewareconfig
loglog
error / stderrlog (level=error)
warninglog (level=warning)
infolog (level=info)
configconfig

何时仍然用 <CodeBlock> 组件

以下场景仍需要 .mdx 文件用 <CodeBlock> 标签:

  • 指定 filePath:<CodeBlock type="config" filePath="/etc/nginx/nginx.conf" label="Nginx" />
  • 指定 vendor:<CodeBlock type="network" vendor="cisco" />
  • 指定 level:<CodeBlock type="log" level="warning" />
  • 指定 title:<CodeBlock type="code" title="示例" />
  • 指定 shell:<CodeBlock type="terminal" shell="powershell" />

这些是 markdown 自动分类拿不到的信息,需要显式传参。


引用与提示块

GFM Alert(自动映射为 Callout)

下面是 tip 提示(绿色):

提示

这是一条提示,渲染为绿色 tip 提示框。
跨多行也支持,每行行首加 >

下面是 warning 警告(黄色):

注意

警告,渲染为黄色注意框。危险操作前必看。

下面是 danger 危险(红色):

危险

危险操作,渲染为红色提示框。

下面是 note 备注(蓝色):

备注

备注,渲染为蓝色提示框。

下面是 info 信息(青色):

信息

信息,渲染为青色提示框。

下面是 success 成功(绿色):

成功

成功,渲染为绿色提示框。

下面是 question 问题(紫色):

问题

问题,渲染为紫色提示框。

下面是 example 示例(靛蓝):

示例

示例,渲染为靛蓝提示框。

署名行(项目惯例)

作者 日期

[!AUTHOR] 后面的文本作为标题,渲染为 note 类型的 Callout。

多行内容示例

提示

第一段内容。

第二段内容,可以包含强调代码链接

  • 列表项 1
  • 列表项 2

普通引用

备注

这是一条普通引用,渲染为原生 blockquote。
跨多行,每行行首加 >

不写 [!TYPE] 前缀就是普通引用。

何时仍然用 <Callout> 组件

以下场景仍需要 .mdx 文件用 <Callout> 标签:

  • 折叠:<Callout type="tip" collapsible collapsed>
  • 自定义图标:<Callout type="note" icon="..." />
  • 嵌套使用(在另一个组件/容器内)

折叠和图标是 GFM alert 语法拿不到的能力,需要用组件。


与 remark-callout(:::)的关系

项目同时支持 GFM alert(> [!TYPE])和 remark-directive(:::TYPE)。两者渲染为相同结构,可混用:

提示

这是 remark-directive 写法,效果和 > [!TIP] 一致。

建议:

  • 简单提示用 > [!TYPE]
  • 需要标题的复杂提示用 :::TYPE[标题]
  • 需要折叠/图标的用 <Callout> 组件