在本站写文章:Markdown、GFM 与 MDC 语法指南
摘要
从 frontmatter 到代码组、提示框和折叠面板,完整介绍 Leisuer Blog 当前支持的文章语法与项目约定。
在本站写文章:Markdown、GFM 与 MDC 语法指南
本站的文章并不只是普通 Markdown。内容会先交给 Nuxt Content 解析,再由 Nuxt UI 的 prose 组件和项目中的自定义组件渲染。因此,除了标题、列表、链接这些基础语法,还可以使用代码高亮、文件名、行号、代码组、提示框和折叠面板。
这篇文章以项目当前的源码为准,整理一份可以直接复制使用的写作手册。
一篇文章的最小结构
每篇文章都由两部分组成:顶部的 frontmatter 和下面的 Markdown 正文。可以从这个模板开始:
---
title: 文章标题
description: 一句话摘要,也会作为页面的 SEO 描述。
created: 2026-09-30
updated: 2026-09-30
category: Notes
tags:
- Markdown
- Nuxt Content
cover: /img/cover/example.webp
pinned: false
draft: false
---
# 文章标题
这里开始写正文。
## 第一个章节
章节内容。
项目当前认识的自定义字段如下:
| 字段 | 类型 | 用途 |
|---|---|---|
title | 字符串 | 页面标题、文章卡片标题和浏览器标题 |
description | 字符串 | 文章摘要和 meta description |
created | 日期 | 发布时间 |
updated | 日期 | 最后修改时间,可省略 |
category | 字符串或字符串数组 | 单级或多级分类 |
tags | 字符串数组 | 标签列表 |
cover | 字符串 | 文章卡片封面地址 |
pinned | 布尔值 | 是否在文章列表中置顶 |
draft | 布尔值 | 是否从文章列表、分类、标签和搜索中隐藏 |
多级分类可以写成数组:
category: [Notes, Nuxt Content]
wordCount 和 readingMinutes 虽然也存在于内容 schema 中,但构建时会根据正文自动计算,通常不需要手写。
如果新增 frontmatter 字段,还要同步修改 content.config.ts 的 schema,否则 Nuxt Content 可能会丢弃这个字段。修改 schema 后,开发服务器通常也需要重启。
标题与目录
Markdown 使用 # 表示标题层级:
# 文章标题
## 一级章节
### 二级章节
#### 更深一层的标题
项目的文章壳会单独显示 frontmatter 中的 title,所以正文里的 # 一级标题 会被隐藏。保留它可以让 Markdown 文件脱离网站后仍有完整结构,但正文内容建议从 ## 开始。
页面会根据标题自动生成锚点和侧边目录。当前目录主要展示二级、三级标题,滚动时会同步高亮所在章节;标题层级应该依次递进,不要只为了字号从 ## 突然跳到 ####。
段落与行内格式
空一行会开始一个新段落。普通换行通常仍属于同一段;如果确实需要强制换行,可以在行尾输入两个空格,或者使用 <br>。
这是第一段,其中有 **粗体**、*斜体*、***粗斜体***、~~删除线~~ 和 `行内代码`。
这是第二段。
这一行会强制换行。
也可以使用 HTML 换行。<br>
这里会显示在下一行。
常用的行内写法:
| 效果 | 写法 |
|---|---|
| 粗体 | **重要内容** |
| 斜体 | *强调内容* |
| 粗斜体 | ***特别强调*** |
| 删除线 | ~~旧内容~~ |
| 行内代码 | `const answer = 42` |
| 高亮 | <mark>高亮内容</mark> |
| 键盘按键 | <kbd>⌘</kbd> + <kbd>K</kbd> |
如果想原样显示 Markdown 符号,可以在它前面添加反斜杠:
\*这段文字不会变成斜体\*
\# 这也不会变成标题
链接与图片
行内链接、自动链接和引用式链接都可以使用:
[Nuxt 官网](https://nuxt.com)
<https://content.nuxt.com>
[Nuxt Content][content-docs]
[content-docs]: https://content.nuxt.com "Nuxt Content 文档"
站内链接可以直接写路径:
[查看关于本站](/posts/about-site)
图片建议放进 public/,并从站点根路径引用:


Nuxt Content 的 MDC 属性还可以控制图片尺寸和类名:
{width="96" height="96"}
{.w-24 .rounded-xl}
{.max-w-md}
所有正文图片默认都会限制在文章宽度内、保持比例并居中显示。替代文本不能省略:除了无障碍访问,它也会在图片加载失败时提供必要信息。
引用、分隔线与列表
引用使用 >,可以包含多个段落或继续嵌套:
> 写作不是把所有内容堆在一起,而是帮助读者建立顺序。
>
> > 嵌套引用适合补充引用中的上下文。
三个连字符可以生成分隔线:
---
无序列表可以使用 -、* 或 +,有序列表使用数字:
- 第一项
- 第二项
- 嵌套项目
- 另一个嵌套项目
1. 第一步
2. 第二步
3. 第三步
任务列表使用 GFM 的复选框语法:
- [x] 已完成
- [ ] 待处理
- [ ] 支持 **粗体** 和 `行内代码`
缩进决定列表的嵌套关系。为了减少不同解析器之间的差异,建议每层统一缩进两个或四个空格。
表格
表格由竖线和表头分隔行组成,分隔行中的冒号控制对齐方式:
| 功能 | 状态 | 备注 |
| :--- | :---: | ---: |
| 普通 Markdown | 支持 | 左对齐 |
| MDC 组件 | 支持 | 居中 |
| 代码高亮 | 支持 | 右对齐 |
| 功能 | 状态 | 备注 |
|---|---|---|
| 普通 Markdown | 支持 | 左对齐 |
| MDC 组件 | 支持 | 居中 |
| 代码高亮 | 支持 | 右对齐 |
文章样式会给表头和隔行添加背景色;表格过宽时可以横向滚动,不会挤破页面。
代码块
三个反引号可以创建围栏代码块,在开头写语言名即可启用语法高亮:
```ts
type Post = {
title: string
tags: string[]
}
const post: Post = {
title: 'Hello Nuxt Content',
tags: ['Nuxt', 'Markdown'],
}
```
渲染后的代码块会自动带有语言标题、macOS 风格顶栏和悬停出现的复制按钮。项目额外配置了 C++ 高亮,也可以使用 js、ts、vue、bash、json、diff、css、html、md 等常见语言标识。
显示文件名
把文件名放在语言标识后的方括号中:
```ts [content.config.ts]
export default defineContentConfig({
collections: {},
})
```
显示行号
在代码块元信息中加入 {.line-numbers}:
```ts [example.ts] {.line-numbers}
const answer = 42
console.log(answer)
```
如果示例来自原文件的第 8 行,可以在文件名后添加起始行号:
```ts [example.ts:8] {.line-numbers}
const answer = 42
console.log(answer)
```
代码组
同一操作有多种写法时,可以用 code-group 把它们组织成标签页:
::code-group
```bash [npm]
npm install
```
```bash [pnpm]
pnpm install
```
```bash [yarn]
yarn install
```
::
实际显示:
npm install
pnpm install
yarn install
缩进不是装饰:代码组中的每个代码块需要缩进到容器内部。
提示框
项目提供了四种提示框:note、tip、warning 和 caution。
::note
用于补充背景信息。
::
::tip{title="小技巧"}
用于给出更高效的做法。
::
::warning{title="请留意"}
用于提醒潜在问题。
::
::caution{title="危险操作"}
用于强调严重后果。
::
实际显示:
在组件名后使用 {title="..."} 即可传入标题。没有自定义标题时,提示框仍会保留对应的颜色和图标。
::
提示框内部仍然可以继续使用 Markdown:
::warning{title="发布前检查"}
- [ ] 日期是否正确
- [ ] 图片是否有替代文本
- [ ] 链接是否能访问
::
折叠内容
需要隐藏补充说明或答案时,可以使用 collapse;希望默认展开时使用 expand:
::collapse{title="点击查看答案"}
这里的内容默认折叠。
::
::expand{title="默认展开的说明"}
这里的内容打开页面时就能看到,也可以手动收起。
::
点击查看一个实际示例
这是由项目中的 ProseCollapse 和 ProseDetails 组件渲染的内容。
- 可以写多个段落
- 也可以放列表与代码块
默认展开的实际示例
这个面板会默认展开,读者仍然可以点击标题将它收起。
details 是同一套底层组件的通用形式,还能传入 open、icon 和 type 等属性:
::details{title="通用详情面板" icon="lucide:book-open"}
这里使用的是 `details` 组件。
::
实际显示:
通用详情面板
这里使用的是 details 组件。日常写作仍建议优先选择语义更明确的 collapse 或 expand。
脚注
脚注适合放来源、解释或不希望打断正文的补充信息:
Nuxt Content 会把 Markdown 转换成可查询的结构化内容。[^content]
[^content]: 详见 Nuxt Content 官方文档。
脚注定义可以包含多行,后续行需要缩进:
这是一条较长的说明。[^long-note]
[^long-note]: 第一行内容。
这是同一条脚注的后续内容。
原生 HTML 与 MDC 组件
Markdown 中可以嵌入少量原生 HTML。项目已经为 <details>、<summary>、<kbd>、<mark> 等元素准备了正文样式:
<details>
<summary>原生折叠区域</summary>
这里是折叠内容。
</details>
按 <kbd>⌘</kbd> + <kbd>K</kbd> 打开搜索。
<mark>这是一段高亮文字。</mark>
MDC 也可以直接调用已注册的 Vue 组件,属性写在花括号中:
::alert{color="#53a3f1"}
这是由 `app/components/Alert.vue` 渲染的内容。
::
::div{class="rounded-lg border p-4"}
这是带有 class 的原生 div 容器。
::
::counter
::
:badge[内联徽章]{color="info"}
::card
### 卡片标题
卡片中也可以继续使用 **Markdown**。
::
实际显示:
这是由 Alert.vue 渲染的提示区域,边框颜色来自传入的 color 属性。
这是一个通过 MDC 创建的 div,样式直接来自传入的 Tailwind class。
Counter: 0
上面的计数器是一个真正可交互的 Vue 组件,点击按钮后数字会立即变化。
行内 Badge 的效果::badge内联徽章
Card 的效果:
这种能力很强,但也会让文章依赖项目内部实现。通用内容优先使用标准 Markdown;只有确实需要交互或特殊布局时,再使用自定义组件。
当前没有启用的语法
测试文档中还包含数学公式和定义列表,但项目目前没有配置数学公式插件或专门的定义列表渲染规则。下面的内容不应假定会得到数学排版:
$E = mc^2$
$$
E = mc^2
$$
术语
: 定义内容
它们可能只会作为普通文本显示。需要公式时,应先为 Nuxt Content 接入相应的 Markdown 插件并补充样式,再在正式文章中使用。
发布前检查清单
- 文件位于
content/,路径和文件名清晰且稳定 - frontmatter 至少包含
title、description、created、category、tags和draft - 正文结构从
##开始,标题层级连续 - 图片使用
public/下的根路径,并填写替代文本 - 代码块标注正确的语言,必要时补充文件名和行号
- 重要说明选择了合适的提示框,而不是只靠加粗或颜色
- 草稿已确认
draft状态,且没有把私密内容当作草稿保存 - 新增 frontmatter 字段时同步更新了
content.config.ts
掌握这些规则后,写作时只需要关心内容本身:基础结构交给 Markdown,复杂展示交给 MDC,文章元信息则统一放在 frontmatter。这样写出的文件既保持可读,也能完整使用本站的目录、分类、搜索、代码高亮和主题样式。