全面的 MDX 格式指南与测试文档
欢迎来到完整的 MDX 格式测试文档。本指南演示了 MDX (Markdown + JSX) 的所有主要特性,包括标准 Markdown 语法、代码块、表格、列表等。本文档既是参考资料,也是对 MDX 渲染器的视觉测试。
目录
简介
MDX 是一种强大的格式,它将 Markdown 的简洁性与 JSX 的灵活性结合在一起。它允许你在 Markdown 内容中无缝导入和使用 React 组件,非常适合技术文档、博客文章和交互式内容。
什么是 MDX?
MDX 代表 Markdown + JSX。它是一种可编写的格式,允许你在 Markdown 文档中嵌入 JSX。这使你能够:
- 使用 Markdown 轻松编写长篇内容
 - 在内容中导入和使用 React 组件
 - 创建交互式示例和演示
 - 构建可重用的内容块
 - 使用 TypeScript 保持类型安全
 
为什么使用 MDX?
使用 MDX 作为你的内容格式有几个令人信服的理由:
- 组件可重用性:编写一次组件,随处使用
 - 交互性:创建引人入胜的交互式文档
 - 类型安全:利用 TypeScript 获得更好的开发体验
 - 灵活性:结合 Markdown 和 React 的优点
 - 开发体验:使用熟悉的工具和语法
 
文本格式化
MDX 支持所有标准的 Markdown 文本格式化选项。让我们详细探讨每一种。
基本文本样式
以下是在 MDX 中设置文本样式的基本方法:
- 粗体文本 使用双星号:
**bold** - 斜体文本 使用单星号:
*italic* - 粗斜体 使用三星号:
***bold and italic*** - ~~删除线~~ 使用双波浪号:
~~strikethrough~~ 内联代码使用反引号:`code`
组合样式
你还可以用有趣的方式组合这些样式:
- 粗体包含 嵌套斜体 文本
 - 斜体包含 嵌套粗体 文本
 - 粗体内部包含 
内联代码 代码内部包含 **粗体**(虽然这可能不会按预期工作)
段落和换行
在 Markdown 中,段落由空行分隔。这是一个单独的段落,它在多行上继续而没有空行,它将被渲染为一个连续的段落。
要创建新段落,只需添加一个空行。
你也可以在行末使用两个空格 来创建换行而不开始新段落。
标题
MDX 支持六个级别的标题,从 H1 到 H6:
一级标题
二级标题
三级标题
四级标题
五级标题
六级标题
标题也可以使用下划线创建(适用于 H1 和 H2):
另一种 H1 样式
另一种 H2 样式
标题最佳实践
- 每个文档只使用一个 H1(通常是标题)
 - 保持逻辑层次结构(不要跳过级别)
 - 保持标题简洁和描述性
 - 一致使用句首大写或标题大写
 
列表
列表对于组织信息至关重要。MDX 支持有序和无序列表,并具有无限嵌套。
无序列表
你可以使用 -、* 或 + 创建无序列表:
- 第一项
 - 第二项
 - 第三项
- 嵌套项 1
 - 嵌套项 2
- 深度嵌套项
 - 另一个深度嵌套项
 
 - 返回第二层
 
 - 第四项
 
有序列表
有序列表使用数字后跟句点:
- 第一步
 - 第二步
 - 第三步
- 子步骤 A
 - 子步骤 B
 - 子步骤 C
 
 - 第四步
 
混合列表
你可以混合有序和无序列表:
- 第一个有序项
- 无序子项
 - 另一个无序子项
 
 - 第二个有序项
- 有序子项
 - 另一个有序子项
- 混合嵌套项
 - 另一个混合嵌套项
 
 
 
任务列表
一些 Markdown 处理器支持任务列表(GitHub 风格):
- [x] 已完成任务
 - [x] 另一个已完成任务
 - [ ] 待完成任务
 - [ ] 另一个待完成任务
- [x] 已完成子任务
 - [ ] 待完成子任务
 
 
定义列表
定义列表非常适合术语表:
术语 1 : 术语 1 的定义
术语 2 : 术语 2 的定义 : 术语 2 的替代定义
代码示例
代码块对于技术文档至关重要。MDX 提供了出色的语法高亮支持。
内联代码
使用单个反引号表示内联代码:const greeting = 'Hello, World!'
你也可以在行内引用 变量、函数() 或 文件名.ts。
基本代码块
使用三个反引号创建代码块:
这是一个没有语法高亮的纯文本代码块。
它保留格式和缩进。TypeScript 示例
// TypeScript 类型示例
interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'user';
}
function getUserById(id: number): User | null {
  // 实现代码
  return null;
}
const user: User = {
  id: 1,
  name: 'John Doe',
  email: 'john@example.com',
  role: 'admin',
};Python 示例
# Python 示例
from typing import List, Optional
from dataclasses import dataclass
@dataclass
class User:
    id: int
    name: str
    email: str
    is_active: bool = True
def get_active_users(users: List[User]) -> List[User]:
    """筛选并返回活跃用户"""
    return [user for user in users if user.is_active]
def find_user_by_email(users: List[User], email: str) -> Optional[User]:
    """通过邮箱地址查找用户"""
    for user in users:
        if user.email == email:
            return user
    return None
# 使用示例
users = [
    User(1, "Alice", "alice@example.com"),
    User(2, "Bob", "bob@example.com", False),
    User(3, "Charlie", "charlie@example.com"),
]
active_users = get_active_users(users)
user = find_user_by_email(users, "alice@example.com")引用块
引用块非常适合突出显示重要信息、引用或标注。
基本引用块
这是一个简单的引用块。它非常适合突出显示重要信息或包含来自其他来源的引用。
嵌套引用块
这是外层引用块。
这是嵌套的引用块。
这是深度嵌套的引用块。
包含多个段落的引用块
这是引用块的第一段。
这是引用块的第二段。你可以通过使用带有
>字符的空行在单个引用块中包含多个段落。这是第三段。
包含其他元素的引用块
引用块中的标题
你可以在引用块中包含 格式化文本、斜体 甚至
代码。
- 列表项 1
 - 列表项 2
 - 列表项 3
 // 甚至代码块! console.log('来自引用块的问候');
不同类型的标注
注意: 这是提供额外上下文的信息性注释。
警告: 这是突出显示潜在问题的警告消息。
提示: 这是提供有用建议的帮助提示。
重要: 这是不应忽视的关键信息。
表格
表格非常适合呈现结构化数据。MDX 支持 GitHub 风格的 Markdown 表格。
基本表格
| 姓名 | 年龄 | 职业 | |---------|-----|-------------| | Alice | 28 | 开发者 | | Bob | 32 | 设计师 | | Charlie | 25 | 产品经理 |
带对齐的表格
| 左对齐 | 居中对齐 | 右对齐 | |:-------------|:--------------:|--------------:| | 左边 | 居中 | 右边 | | 文本 | 文本 | 文本 | | 更多 | 数据 | 这里 |
复杂表格
| 功能 | 免费版 | 专业版 | 企业版 | |---------|:----:|:---:|:----------:| | 用户数 | 5 | 25 | 无限 | | 存储空间 | 10 GB | 100 GB | 无限 | | 支持 | 邮件 | 优先 | 24/7 电话 | | API 访问 | ❌ | ✅ | ✅ | | 自定义域名 | ❌ | ✅ | ✅ | | 分析 | 基础 | 高级 | 定制 | | 价格 | 29/月 | 联系我们 |
包含代码的表格
| 方法 | 端点 | 描述 |
|--------|----------|-------------|
| GET | /api/users | 获取所有用户 |
| GET | /api/users/:id | 获取特定用户 |
| POST | /api/users | 创建新用户 |
| PUT | /api/users/:id | 更新用户 |
| DELETE | /api/users/:id | 删除用户 |
对比表格
| 功能 | React | Vue | Angular | Svelte | |---------|-------|-----|---------|--------| | 学习曲线 | 中等 | 容易 | 陡峭 | 容易 | | 性能 | 优秀 | 优秀 | 良好 | 优秀 | | 打包大小 | 中等 | 小 | 大 | 极小 | | TypeScript | ✅ | ✅ | ✅ (内置) | ✅ | | 社区 | 庞大 | 大 | 大 | 增长中 | | 支持方 | Meta | 独立 | Google | 独立 |
链接和图片
基本链接
这是一个到 Google 的链接。
你也可以使用引用式链接,像这样。
带标题的链接
这是一个带标题的链接:MDN Web Docs。
自动链接
URL 和电子邮件地址可以自动转换为链接:
- https://www.github.com
 - contact@example.com
 
内部链接
图片语法
Markdown 中的图片使用类似于链接的语法:
![]()
带链接的图片
你可以通过将图片包装在链接中使其可点击:
高级 MDX 特性
MDX 超越了标准 Markdown,允许你在内容中直接使用 JSX 和 React 组件。
导入组件
在 MDX 中,你可以导入和使用 React 组件:
import { CustomComponent } from '@/components/CustomComponent'
<CustomComponent prop1="value1" prop2="value2" />内联 JSX
你可以在 MDX 中直接编写 JSX:
<div className="custom-wrapper">
  <h3>自定义标题</h3>
  <p>这是 JSX 内容!</p>
</div>使用 JavaScript 表达式
MDX 支持 JavaScript 表达式:
当前年份是 {new Date().getFullYear()}。
随机数:{Math.floor(Math.random() * 100)}组件属性
你可以向组件传递属性,包括函数:
<Button
  onClick={() => alert('已点击!')}
  variant="primary"
  size="large"
>
  点击我
</Button>条件渲染
{true && <p>这将被渲染</p>}
{false && <p>这不会被渲染</p>}
{condition ? <ComponentA /> : <ComponentB />}遍历数组
{['React', 'Vue', 'Angular', 'Svelte'].map((framework) => (
  <Badge key={framework}>{framework}</Badge>
))}高级模式
自定义 MDX 组件
你可以用自定义组件替换默认的 Markdown 元素:
// mdx-components.tsx
import type { MDXComponents } from 'mdx/types'
import { Code } from '@/components/Code'
import { Heading } from '@/components/Heading'
import { Image } from '@/components/Image'
export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    h1: (props) => <Heading level={1} {...props} />,
    h2: (props) => <Heading level={2} {...props} />,
    h3: (props) => <Heading level={3} {...props} />,
    code: (props) => <Code {...props} />,
    img: (props) => <Image {...props} />,
    ...components,
  }
}语法高亮
对于高级语法高亮,你可以使用 Shiki 或 Prism 等库:
import { getHighlighter } from 'shiki'
export async function highlightCode(code: string, lang: string) {
  const highlighter = await getHighlighter({
    themes: ['github-dark', 'github-light'],
    langs: ['javascript', 'typescript', 'jsx', 'tsx', 'python', 'rust'],
  })
  return highlighter.codeToHtml(code, {
    lang,
    themes: {
      light: 'github-light',
      dark: 'github-dark',
    },
  })
}Frontmatter 处理
处理 MDX 文件中的 frontmatter 元数据:
interface FrontMatter {
  title: string
  description: string
  date: string
  author: string
  tags: string[]
  published: boolean
}
export function processFrontMatter(frontmatter: FrontMatter) {
  return {
    ...frontmatter,
    date: new Date(frontmatter.date),
    tags: frontmatter.tags.map(tag => tag.toLowerCase()),
  }
}动态内容加载
动态加载 MDX 内容:
import fs from 'fs/promises'
import path from 'path'
import matter from 'gray-matter'
export async function getMDXContent(slug: string) {
  const filePath = path.join(process.cwd(), 'content', `${slug}.mdx`)
  const source = await fs.readFile(filePath, 'utf-8')
  const { content, data } = matter(source)
  return {
    content,
    frontmatter: data,
  }
}
export async function getAllPosts() {
  const contentDir = path.join(process.cwd(), 'content')
  const files = await fs.readdir(contentDir)
  const posts = await Promise.all(
    files
      .filter(file => file.endsWith('.mdx'))
      .map(async file => {
        const slug = file.replace(/\.mdx$/, '')
        const content = await getMDXContent(slug)
        return { slug, ...content }
      })
  )
  return posts.sort((a, b) => {
    return new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime()
  })
}数学表达式
如果你的 MDX 设置支持数学公式(通过 remark-math 或 KaTeX),你可以包含数学表达式。以下是如何编写它们的示例:
内联数学
对于内联数学,你通常使用单美元符号或括号表示法:
内联数学:$E = mc^2$ 或 \(E = mc^2\)块级数学
对于显示数学块,使用双美元符号或方括号表示法: