{
    "version": "https://jsonfeed.org/version/1",
    "title": "Bean Blog",
    "home_page_url": "https://ccbeango.github.io",
    "feed_url": "https://ccbeango.github.io/feed.json",
    "description": "记录工程实践、技术思考与持续学习。",
    "icon": "https://ccbeango.github.io/favicon.png",
    "author": {
        "name": "Bean",
        "url": "https://ccbeango.github.io"
    },
    "items": [
        {
            "id": "https://ccbeango.github.io/blog/guide/getting-started",
            "content_html": "<p>Bean Blog 是一个基于 VitePress 2、Vue 3、TypeScript 和 Tailwind CSS 4 的静态博客。文章保存在仓库中，发布时生成纯静态页面，不需要数据库或应用服务器。</p>\n<h2 id=\"环境要求\" tabindex=\"-1\">环境要求 <a class=\"header-anchor\" href=\"#环境要求\" aria-label=\"Permalink to “环境要求”\">&#8203;</a></h2>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>工具</th>\n<th>要求</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Node.js</td>\n<td>22.12 或更高版本</td>\n</tr>\n<tr>\n<td>pnpm</td>\n<td>11.24.0</td>\n</tr>\n<tr>\n<td>VitePress</td>\n<td>精确锁定为 <code>2.0.0-alpha.19</code></td>\n</tr>\n</tbody>\n</table>\n<p>VitePress 当前使用 alpha 版本，因此升级版本后应重新检查 Markdown 渲染、标题锚点、系列导航和主题行为。</p>\n<h2 id=\"安装依赖\" tabindex=\"-1\">安装依赖 <a class=\"header-anchor\" href=\"#安装依赖\" aria-label=\"Permalink to “安装依赖”\">&#8203;</a></h2>\n<p>在项目根目录执行：</p>\n<div class=\"language-powershell line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">powershell</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm install </span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">--</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">frozen</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">-</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">lockfile</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div><p><code>pnpm-lock.yaml</code> 已固定完整依赖树。除非确实需要升级依赖，否则不要删除 lockfile 或改用其他包管理器重新生成。</p>\n<h2 id=\"运行开发环境\" tabindex=\"-1\">运行开发环境 <a class=\"header-anchor\" href=\"#运行开发环境\" aria-label=\"Permalink to “运行开发环境”\">&#8203;</a></h2>\n<div class=\"language-powershell line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">powershell</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm dev</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div><p>默认地址为 <code>http://localhost:5173</code>。正文修改支持热更新；新增文章，或修改文章标题、系列归属与排序后，需要重启开发服务，因为系列 sidebar 在 VitePress 配置阶段生成。</p>\n<p>开发环境会显示 <code>draft: true</code> 的文章并标记为草稿。生产构建会从路由、列表、搜索、归档、标签、 sitemap 和 feed 中排除草稿。</p>\n<h2 id=\"项目目录\" tabindex=\"-1\">项目目录 <a class=\"header-anchor\" href=\"#项目目录\" aria-label=\"Permalink to “项目目录”\">&#8203;</a></h2>\n<div class=\"language-text line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">text</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span>packages/</span></span>\n<span class=\"line\"><span>  lxgw-wenkai-lite-webfont/ # 自托管中文字体子包</span></span>\n<span class=\"line\"><span>src/</span></span>\n<span class=\"line\"><span>  .vitepress/</span></span>\n<span class=\"line\"><span>    build/                  # robots、manifest 与 feed</span></span>\n<span class=\"line\"><span>    data/                   # 文章校验和集合转换</span></span>\n<span class=\"line\"><span>    markdown/               # 图片与 Live Photo 扩展</span></span>\n<span class=\"line\"><span>    theme/                  # 自定义主题与 Tailwind 入口</span></span>\n<span class=\"line\"><span>    config.ts               # VitePress 配置</span></span>\n<span class=\"line\"><span>    site.config.ts          # 站点身份和第三方配置</span></span>\n<span class=\"line\"><span>  posts/                    # Markdown 文章来源</span></span>\n<span class=\"line\"><span>    guide/                  # 当前使用手册</span></span>\n<span class=\"line\"><span>  public/                   # 图标、封面和文章媒体</span></span>\n<span class=\"line\"><span>  blog/                     # /blog 动态路由入口</span></span>\n<span class=\"line\"><span>tests/                      # Vitest 与 Playwright</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br><span class=\"line-number\">7</span><br><span class=\"line-number\">8</span><br><span class=\"line-number\">9</span><br><span class=\"line-number\">10</span><br><span class=\"line-number\">11</span><br><span class=\"line-number\">12</span><br><span class=\"line-number\">13</span><br><span class=\"line-number\">14</span><br><span class=\"line-number\">15</span><br></div></div><p><code>src/posts</code> 的目录不会公开为 <code>/posts</code>。文章文件的相对路径会转换为 <code>/blog/&lt;nested-slug&gt;</code>。</p>\n<h2 id=\"常用命令\" tabindex=\"-1\">常用命令 <a class=\"header-anchor\" href=\"#常用命令\" aria-label=\"Permalink to “常用命令”\">&#8203;</a></h2>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>命令</th>\n<th>用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>pnpm dev</code></td>\n<td>启动开发服务并预览草稿</td>\n</tr>\n<tr>\n<td><code>pnpm format</code></td>\n<td>使用 ESLint 格式化代码和排序 Tailwind class</td>\n</tr>\n<tr>\n<td><code>pnpm lint</code></td>\n<td>检查代码规范与格式</td>\n</tr>\n<tr>\n<td><code>pnpm typecheck</code></td>\n<td>检查 TypeScript 与 Vue 类型</td>\n</tr>\n<tr>\n<td><code>pnpm test</code></td>\n<td>运行单元测试</td>\n</tr>\n<tr>\n<td><code>pnpm audit:styles</code></td>\n<td>检查 Tailwind authored styles 边界</td>\n</tr>\n<tr>\n<td><code>pnpm build</code></td>\n<td>生成生产静态站点</td>\n</tr>\n<tr>\n<td><code>pnpm test:e2e</code></td>\n<td>运行浏览器回归测试</td>\n</tr>\n</tbody>\n</table>\n<p>项目不使用 Prettier，也不启用 <code>@antfu/eslint-config</code> 的外部 <code>formatters</code>。VS Code 的保存修复与 <code>Alt+Shift+F</code>、命令行的 <code>pnpm format</code> 都读取同一份 ESLint Flat Config。</p>\n<p><code>.editorconfig</code>、<code>.gitattributes</code> 和工作区 VS Code 设置统一使用 LF，并保证文件末尾换行。JS、TS 与 Vue 代码最多 120 字符；URL、字符串、模板字符串、正则和独立 Tailwind <code>class</code> 属性行不强制拆断。Vue 标签有多个属性时，ESLint 会自动整理为每行一个属性；无法安全自动重排的 TypeScript 长表达式会由 <code>pnpm lint</code> 报告，需要按语义手工换行。</p>\n<p>主题不使用 Tailwind 默认色板。颜色、排版、布局尺寸、控件尺寸、圆角、容器、层级、阴影、模糊、媒体比例和动效统一定义在 <code>src/.vitepress/theme/tailwind.css</code>；颜色值全部使用 <code>oklab()</code>。暗色模式通过根节点的 <code>dark:theme-dark</code> 覆盖同名 token，因此普通组件无需为同一语义重复编写 <code>dark:</code> 颜色。完整命名和扩展规则见<a href=\"/blog/guide/site-configuration#主题设计令牌\">配置站点信息</a>。</p>\n<h2 id=\"下一步\" tabindex=\"-1\">下一步 <a class=\"header-anchor\" href=\"#下一步\" aria-label=\"Permalink to “下一步”\">&#8203;</a></h2>\n<ul>\n<li><a href=\"/blog/guide/site-configuration\">配置站点信息</a></li>\n<li><a href=\"/blog/guide/writing-articles\">创建和组织文章</a></li>\n<li><a href=\"/blog/guide/markdown-extensions\">使用 Markdown 扩展</a></li>\n<li><a href=\"/blog/guide/deployment\">部署静态站点</a></li>\n</ul>\n",
            "url": "https://ccbeango.github.io/blog/guide/getting-started",
            "title": "开始使用 Bean Blog",
            "summary": "安装依赖、启动开发服务，并了解 Bean Blog 的目录结构与日常命令。",
            "date_modified": "2026-09-02T00:00:00.000Z",
            "date_published": "2026-09-02T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/site-configuration",
            "content_html": "<p>项目有两个配置入口，它们服务于不同层级：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>文件</th>\n<th>职责</th>\n<th>什么时候修改</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>src/.vitepress/site.config.ts</code></td>\n<td>站点名称、作者、导航、社交入口、分页、图标、Feed 和评论</td>\n<td>搭建自己的博客时需要修改</td>\n</tr>\n<tr>\n<td><code>src/.vitepress/config.ts</code></td>\n<td>VitePress 路由、Markdown、侧栏、SEO、资源注入和构建钩子</td>\n<td>调整工程能力时才修改</td>\n</tr>\n</tbody>\n</table>\n<p>日常配置优先集中在 <code>site.config.ts</code>。页面组件和构建逻辑会读取这里的数据，不应在组件中重复写作者名称、域名或社交账号。</p>\n<h2 id=\"环境变量\" tabindex=\"-1\">环境变量 <a class=\"header-anchor\" href=\"#环境变量\" aria-label=\"Permalink to “环境变量”\">&#8203;</a></h2>\n<p>域名和部署路径由环境变量注入，不建议硬编码到 <code>site.config.ts</code>。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>变量</th>\n<th>必填</th>\n<th>用途</th>\n<th>示例值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>SITE_URL</code></td>\n<td>生产构建必填</td>\n<td>站点完整来源地址，用于 canonical、Open Graph、sitemap、robots 和 Feed</td>\n<td><code>https://username.github.io</code></td>\n</tr>\n<tr>\n<td><code>SITE_BASE</code></td>\n<td>否</td>\n<td>站点部署子路径；根站点使用 <code>/</code></td>\n<td><code>/</code> 或 <code>/blog/</code></td>\n</tr>\n</tbody>\n</table>\n<p><code>SITE_URL</code> 不包含末尾 <code>/</code>。<code>SITE_BASE</code> 应同时保留开头和结尾的 <code>/</code>；未设置或设置为 <code>/</code> 时表示部署在域名根路径。</p>\n<p>本地开发不要求 <code>SITE_URL</code>。需要检查生产输出时，项目已提供固定占位域名的命令：</p>\n<div class=\"language-powershell line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">powershell</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm build:local</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm preview</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br></div></div><p>GitHub Pages workflow 在 <code>.github/workflows/deploy.yml</code> 中声明：</p>\n<div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">env</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  SITE_URL</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">https://${{ github.repository_owner }}.github.io</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  SITE_BASE</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">/</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><p>如果仓库发布到项目子路径，需要把 <code>SITE_BASE</code> 改成 <code>/&lt;repository&gt;/</code>，并保证 Pages 的实际访问路径与之相同。</p>\n<h2 id=\"站点信息\" tabindex=\"-1\">站点信息 <a class=\"header-anchor\" href=\"#站点信息\" aria-label=\"Permalink to “站点信息”\">&#8203;</a></h2>\n<p><code>siteConfig.site</code> 控制全站公共信息和输出路径。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>类型</th>\n<th>建议修改</th>\n<th>用途</th>\n<th>当前值示例</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>title</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>VitePress 站点标题、页面标题后缀和首页标题</td>\n<td><code>Bean Blog</code></td>\n</tr>\n<tr>\n<td><code>name</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>页头品牌名和 Web App Manifest 名称</td>\n<td><code>Bean Blog</code></td>\n</tr>\n<tr>\n<td><code>description</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>默认站点描述；页面未单独声明时用于 SEO 和 Feed</td>\n<td><code>记录工程实践、技术思考与持续学习。</code></td>\n</tr>\n<tr>\n<td><code>keywords</code></td>\n<td><code>string[]</code></td>\n<td>是</td>\n<td>普通页面的默认 SEO 关键词</td>\n<td><code>[&quot;VitePress&quot;, &quot;前端开发&quot;]</code></td>\n</tr>\n<tr>\n<td><code>url</code></td>\n<td><code>string</code></td>\n<td>否</td>\n<td>从 <code>SITE_URL</code> 读取并移除末尾 <code>/</code></td>\n<td><code>https://username.github.io</code></td>\n</tr>\n<tr>\n<td><code>base</code></td>\n<td><code>string</code></td>\n<td>否</td>\n<td>从 <code>SITE_BASE</code> 或 Vite <code>BASE_URL</code> 读取并规范为首尾带 <code>/</code> 的路径</td>\n<td><code>/</code></td>\n</tr>\n<tr>\n<td><code>locale</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>Open Graph 地区代码</td>\n<td><code>zh_CN</code></td>\n</tr>\n<tr>\n<td><code>language</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>HTML、VitePress 和 Feed 的语言代码</td>\n<td><code>zh-CN</code></td>\n</tr>\n<tr>\n<td><code>featuredPostsLimit</code></td>\n<td><code>number</code></td>\n<td>按需</td>\n<td>首页“推荐阅读”最多展示的最新文章数量</td>\n<td><code>5</code></td>\n</tr>\n<tr>\n<td><code>postsPerPage</code></td>\n<td><code>number</code></td>\n<td>按需</td>\n<td>文章列表每页显示的文章数量</td>\n<td><code>3</code></td>\n</tr>\n<tr>\n<td><code>favicon</code></td>\n<td><code>object</code></td>\n<td>是</td>\n<td>浏览器和设备图标路径，字段见下表</td>\n<td>见下表</td>\n</tr>\n<tr>\n<td><code>manifest</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>Web App Manifest 的公开路径</td>\n<td><code>/site.webmanifest</code></td>\n</tr>\n<tr>\n<td><code>feeds</code></td>\n<td><code>object</code></td>\n<td>按需</td>\n<td>RSS、Atom 和 JSON Feed 的输出路径</td>\n<td>见下表</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"图标配置\" tabindex=\"-1\">图标配置 <a class=\"header-anchor\" href=\"#图标配置\" aria-label=\"Permalink to “图标配置”\">&#8203;</a></h3>\n<p><code>favicon</code> 的文件应保存在 <code>src/public</code>，配置值使用以 <code>/</code> 开头的公开路径。构建时会自动拼接 <code>SITE_BASE</code>。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>类型</th>\n<th>建议修改</th>\n<th>用途</th>\n<th>当前值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>favicon.ico</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>兼容性 favicon</td>\n<td><code>/favicon.ico</code></td>\n</tr>\n<tr>\n<td><code>favicon.png</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>PNG favicon</td>\n<td><code>/favicon.png</code></td>\n</tr>\n<tr>\n<td><code>favicon.svg</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>SVG favicon</td>\n<td><code>/favicon.svg</code></td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"feed-配置\" tabindex=\"-1\">Feed 配置 <a class=\"header-anchor\" href=\"#feed-配置\" aria-label=\"Permalink to “Feed 配置”\">&#8203;</a></h3>\n<p>这些路径同时用于静态文件生成、页面 <code>&lt;head&gt;</code> 声明和站内 RSS 链接。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>类型</th>\n<th>建议修改</th>\n<th>用途</th>\n<th>当前值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>feeds.rss</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>RSS 2.0 主地址</td>\n<td><code>/rss.xml</code></td>\n</tr>\n<tr>\n<td><code>feeds.rssAlias</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>RSS 兼容别名</td>\n<td><code>/index.xml</code></td>\n</tr>\n<tr>\n<td><code>feeds.atom</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>Atom Feed 地址</td>\n<td><code>/atom.xml</code></td>\n</tr>\n<tr>\n<td><code>feeds.json</code></td>\n<td><code>string</code></td>\n<td>按需</td>\n<td>JSON Feed 地址</td>\n<td><code>/feed.json</code></td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"作者信息\" tabindex=\"-1\">作者信息 <a class=\"header-anchor\" href=\"#作者信息\" aria-label=\"Permalink to “作者信息”\">&#8203;</a></h2>\n<p><code>siteConfig.author</code> 用于首页、文章信息和 Feed 作者信息。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>类型</th>\n<th>建议修改</th>\n<th>用途</th>\n<th>当前值示例</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>name</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>作者显示名称</td>\n<td><code>Bean</code></td>\n</tr>\n<tr>\n<td><code>email</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>Feed 等输出中的作者邮箱</td>\n<td><code>hello@example.com</code></td>\n</tr>\n<tr>\n<td><code>bio</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>首页作者简介</td>\n<td><code>一名持续学习的软件工程师。</code></td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"导航配置\" tabindex=\"-1\">导航配置 <a class=\"header-anchor\" href=\"#导航配置\" aria-label=\"Permalink to “导航配置”\">&#8203;</a></h2>\n<p><code>siteConfig.navigation</code> 是 <code>NavItem[]</code>。有 <code>href</code> 的项目是直接链接，有 <code>children</code> 的项目显示为下拉菜单；<code>children</code> 仍是 <code>NavItem[]</code>，因此支持继续嵌套。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th><code>NavItem</code> 字段</th>\n<th>类型</th>\n<th>必填</th>\n<th>用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>title</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>导航显示文字</td>\n</tr>\n<tr>\n<td><code>href</code></td>\n<td><code>string</code></td>\n<td>否</td>\n<td>目标地址；内部地址以 <code>/</code> 开头，外部地址使用完整 HTTPS URL</td>\n</tr>\n<tr>\n<td><code>children</code></td>\n<td><code>NavItem[]</code></td>\n<td>否</td>\n<td>子导航列表</td>\n</tr>\n</tbody>\n</table>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> navigation</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  { title: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"文章\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"/blog\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  { title: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"使用手册\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"/blog/guide/getting-started\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    title: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"浏览\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    children: [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      { title: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"标签\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"/tags\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      { title: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"归档\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"/archives\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    ],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">];</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br><span class=\"line-number\">7</span><br><span class=\"line-number\">8</span><br><span class=\"line-number\">9</span><br><span class=\"line-number\">10</span><br><span class=\"line-number\">11</span><br></div></div><h2 id=\"社交入口\" tabindex=\"-1\">社交入口 <a class=\"header-anchor\" href=\"#社交入口\" aria-label=\"Permalink to “社交入口”\">&#8203;</a></h2>\n<p><code>homeSocials</code> 控制首页的文字社交入口。Header 只保留导航、搜索和主题切换，不显示社交图标。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th><code>SocialLink</code> 字段</th>\n<th>类型</th>\n<th>必填</th>\n<th>用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>label</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>首页显示文字和链接的无障碍名称</td>\n</tr>\n<tr>\n<td><code>href</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>平台地址或站内 Feed 地址</td>\n</tr>\n</tbody>\n</table>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> homeSocials</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  { label: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"GitHub\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"https://github.com/username\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  { label: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"RSS\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, href: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"/rss.xml\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">];</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br></div></div><p>没有有效地址的平台应直接从数组中移除，不保留空链接。</p>\n<h2 id=\"giscus-评论\" tabindex=\"-1\">Giscus 评论 <a class=\"header-anchor\" href=\"#giscus-评论\" aria-label=\"Permalink to “Giscus 评论”\">&#8203;</a></h2>\n<p><code>siteConfig.giscus</code> 的类型是 <code>GiscusConfig | null</code>。不需要评论时保持 <code>null</code>；启用前先在 Giscus 获取仓库和分类参数。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>类型</th>\n<th>必填</th>\n<th>用途</th>\n<th>常用值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>repo</code></td>\n<td><code>`${string}/${string}`</code></td>\n<td>是</td>\n<td>已启用 Discussions 的公开仓库</td>\n<td><code>owner/repository</code></td>\n</tr>\n<tr>\n<td><code>repoId</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>Giscus 提供的仓库 ID</td>\n<td><code>R_...</code></td>\n</tr>\n<tr>\n<td><code>category</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>Discussion 分类名称</td>\n<td><code>Announcements</code></td>\n</tr>\n<tr>\n<td><code>categoryId</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>Giscus 提供的分类 ID</td>\n<td><code>DIC_...</code></td>\n</tr>\n<tr>\n<td><code>mapping</code></td>\n<td><code>&quot;pathname&quot; | &quot;url&quot; | &quot;title&quot; | &quot;og:title&quot;</code></td>\n<td>是</td>\n<td>页面与 Discussion 的映射方式</td>\n<td><code>pathname</code></td>\n</tr>\n<tr>\n<td><code>reactionsEnabled</code></td>\n<td><code>&quot;0&quot; | &quot;1&quot;</code></td>\n<td>是</td>\n<td>是否启用主贴表态</td>\n<td><code>&quot;1&quot;</code></td>\n</tr>\n<tr>\n<td><code>inputPosition</code></td>\n<td><code>&quot;top&quot; | &quot;bottom&quot;</code></td>\n<td>是</td>\n<td>评论输入框位置</td>\n<td><code>&quot;bottom&quot;</code></td>\n</tr>\n<tr>\n<td><code>lang</code></td>\n<td><code>string</code></td>\n<td>是</td>\n<td>Giscus 界面语言</td>\n<td><code>zh-CN</code></td>\n</tr>\n</tbody>\n</table>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> giscus</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  repo: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"owner/repository\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  repoId: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"R_...\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  category: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"Announcements\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  categoryId: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"DIC_...\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  mapping: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"pathname\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  reactionsEnabled: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"1\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  inputPosition: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"bottom\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  lang: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"zh-CN\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">};</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br><span class=\"line-number\">7</span><br><span class=\"line-number\">8</span><br><span class=\"line-number\">9</span><br><span class=\"line-number\">10</span><br></div></div><p>全部字段有效时评论区才会加载。组件固定使用 <code>strict=&quot;0&quot;</code>、<code>emit-metadata=&quot;0&quot;</code> 和 <code>loading=&quot;lazy&quot;</code>；评论主题会自动跟随 VitePress 的 <code>appearance</code> 状态，不需要在配置中重复声明。</p>\n<h2 id=\"vitepress-基础配置\" tabindex=\"-1\">VitePress 基础配置 <a class=\"header-anchor\" href=\"#vitepress-基础配置\" aria-label=\"Permalink to “VitePress 基础配置”\">&#8203;</a></h2>\n<p><code>src/.vitepress/config.ts</code> 导出异步 <code>UserConfigFn&lt;DefaultTheme.Config&gt;</code>。它组合 <code>site.config.ts</code>、文章数据和 Markdown plugins，属于工程基础设施；只更换博客信息时不需要改这个文件。</p>\n<h3 id=\"顶层选项\" tabindex=\"-1\">顶层选项 <a class=\"header-anchor\" href=\"#顶层选项\" aria-label=\"Permalink to “顶层选项”\">&#8203;</a></h3>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>当前值或来源</th>\n<th>建议修改</th>\n<th>作用</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>lang</code></td>\n<td><code>siteConfig.site.language</code></td>\n<td>否</td>\n<td>设置文档和 HTML 语言</td>\n</tr>\n<tr>\n<td><code>title</code></td>\n<td><code>siteConfig.site.title</code></td>\n<td>否</td>\n<td>设置全站标题</td>\n</tr>\n<tr>\n<td><code>titleTemplate</code></td>\n<td><code>`:title | ${siteConfig.site.title}`</code></td>\n<td>按需</td>\n<td>组合页面标题与站点标题</td>\n</tr>\n<tr>\n<td><code>description</code></td>\n<td><code>siteConfig.site.description</code></td>\n<td>否</td>\n<td>设置默认页面描述</td>\n</tr>\n<tr>\n<td><code>base</code></td>\n<td><code>siteConfig.site.base</code></td>\n<td>否</td>\n<td>设置 VitePress 部署基础路径</td>\n</tr>\n<tr>\n<td><code>srcExclude</code></td>\n<td><code>[&quot;posts/**/*.md&quot;]</code></td>\n<td>否</td>\n<td>不让源文章直接生成 <code>/posts/...</code> 页面；文章由 <code>/blog</code> 动态路由统一发布</td>\n</tr>\n<tr>\n<td><code>cleanUrls</code></td>\n<td><code>true</code></td>\n<td>按需</td>\n<td>生成不带 <code>.html</code> 的公开 URL</td>\n</tr>\n<tr>\n<td><code>lastUpdated</code></td>\n<td><code>true</code></td>\n<td>按需</td>\n<td>让 VitePress 收集 Git 最后更新时间</td>\n</tr>\n<tr>\n<td><code>appearance</code></td>\n<td><code>true</code></td>\n<td>按需</td>\n<td>启用 VitePress 明暗模式状态和切换能力</td>\n</tr>\n<tr>\n<td><code>themeConfig.sidebar</code></td>\n<td>自动生成</td>\n<td>否</td>\n<td>根据文章 frontmatter 的 <code>series</code> 生成官方格式 sidebar</td>\n</tr>\n<tr>\n<td><code>vite.plugins</code></td>\n<td><code>[tailwindcss()]</code></td>\n<td>否</td>\n<td>使用 Tailwind CSS 4 的 Vite plugin 处理主题样式</td>\n</tr>\n</tbody>\n</table>\n<p>配置函数还会根据 <code>command</code> 区分环境：开发服务的系列侧栏包含草稿，生产构建会排除草稿；执行生产构建前调用 <code>requireSiteUrl()</code>，缺少 <code>SITE_URL</code> 时主动失败，避免发布带错误绝对地址的页面。</p>\n<h3 id=\"markdown-选项\" tabindex=\"-1\">Markdown 选项 <a class=\"header-anchor\" href=\"#markdown-选项\" aria-label=\"Permalink to “Markdown 选项”\">&#8203;</a></h3>\n<p>这些能力由 VitePress 官方 Markdown 配置和 markdown-it plugins 提供，自定义主题只负责展示，不重复实现解析行为。</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>当前值</th>\n<th>作用</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>markdown.lineNumbers</code></td>\n<td><code>true</code></td>\n<td>代码块显示行号</td>\n</tr>\n<tr>\n<td><code>markdown.math</code></td>\n<td><code>true</code></td>\n<td>启用数学公式解析</td>\n</tr>\n<tr>\n<td><code>markdown.image.lazyLoad</code></td>\n<td><code>true</code></td>\n<td>为普通 Markdown 图片启用原生懒加载</td>\n</tr>\n<tr>\n<td><code>markdown.codeCopyButton.tooltipText</code></td>\n<td><code>复制代码</code></td>\n<td>复制按钮默认提示文字</td>\n</tr>\n<tr>\n<td><code>markdown.codeCopyButton.copiedText</code></td>\n<td><code>已复制</code></td>\n<td>复制成功后的提示文字</td>\n</tr>\n<tr>\n<td><code>markdown.theme.light</code></td>\n<td><code>github-light</code></td>\n<td>亮色模式 Shiki 代码主题</td>\n</tr>\n<tr>\n<td><code>markdown.theme.dark</code></td>\n<td><code>github-dark</code></td>\n<td>暗色模式 Shiki 代码主题</td>\n</tr>\n</tbody>\n</table>\n<p>Custom Containers 使用 VitePress 保留的英文关键字，界面标题改为中文：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>英文关键字</th>\n<th>默认中文标题</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>info</code></td>\n<td>信息</td>\n</tr>\n<tr>\n<td><code>note</code></td>\n<td>备注</td>\n</tr>\n<tr>\n<td><code>tip</code></td>\n<td>提示</td>\n</tr>\n<tr>\n<td><code>important</code></td>\n<td>重要</td>\n</tr>\n<tr>\n<td><code>warning</code></td>\n<td>警告</td>\n</tr>\n<tr>\n<td><code>danger</code></td>\n<td>危险</td>\n</tr>\n<tr>\n<td><code>caution</code></td>\n<td>注意</td>\n</tr>\n<tr>\n<td><code>details</code></td>\n<td>详细信息</td>\n</tr>\n<tr>\n<td><code>image-grid</code></td>\n<td>图片布局</td>\n</tr>\n<tr>\n<td><code>live-photo</code></td>\n<td>Live Photo</td>\n</tr>\n</tbody>\n</table>\n<p><code>markdown.config(md)</code> 依次注册下列 plugins：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>plugin</th>\n<th>作用</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>markdown-it-task-lists</code></td>\n<td>将 Markdown 任务列表转换为可访问的 checkbox markup</td>\n</tr>\n<tr>\n<td><code>imageGridPlugin</code></td>\n<td>解析 <code>::: image-grid</code> 多图布局</td>\n</tr>\n<tr>\n<td><code>livePhotoPlugin</code></td>\n<td>解析 <code>::: live-photo</code> 并输出可播放的 Motion Photo</td>\n</tr>\n<tr>\n<td><code>photoPreviewPlugin</code></td>\n<td>为普通图片和图片布局补充统一照片预览数据</td>\n</tr>\n</tbody>\n</table>\n<p>具体写法分别见《使用 Markdown 扩展》《编排多图布局》和《使用 Live Photo》章节。</p>\n<h3 id=\"sitemap、head-与构建钩子\" tabindex=\"-1\">Sitemap、head 与构建钩子 <a class=\"header-anchor\" href=\"#sitemap、head-与构建钩子\" aria-label=\"Permalink to “Sitemap、head 与构建钩子”\">&#8203;</a></h3>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>配置</th>\n<th>启用条件</th>\n<th>作用</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>sitemap.hostname</code></td>\n<td>存在 <code>SITE_URL</code></td>\n<td>使用站点来源地址生成 sitemap</td>\n</tr>\n<tr>\n<td><code>sitemap.transformItems</code></td>\n<td>sitemap 已启用</td>\n<td>从 sitemap 中排除 404 页面</td>\n</tr>\n<tr>\n<td><code>head</code></td>\n<td>始终</td>\n<td>注入 favicon、manifest、RSS、Atom 和 JSON Feed 链接</td>\n</tr>\n<tr>\n<td><code>transformHead</code></td>\n<td>每个页面</td>\n<td>生成 description、keywords、canonical、Open Graph 和 Twitter Card metadata</td>\n</tr>\n<tr>\n<td><code>buildEnd</code></td>\n<td>构建结束</td>\n<td>调用 <code>generateStaticAssets(config.outDir)</code> 生成 Feed、robots 和 manifest 等静态文件</td>\n</tr>\n</tbody>\n</table>\n<p><code>transformHead</code> 优先使用动态页面参数中的 <code>title</code>、<code>description</code>、<code>keywords</code>、<code>url</code> 和 <code>canonical</code>，缺失时回退到页面数据及 <code>siteConfig.site</code>。带文章 <code>slug</code> 的页面输出 <code>og:type=article</code>，其它页面输出 <code>website</code>。</p>\n<h2 id=\"配置辅助函数\" tabindex=\"-1\">配置辅助函数 <a class=\"header-anchor\" href=\"#配置辅助函数\" aria-label=\"Permalink to “配置辅助函数”\">&#8203;</a></h2>\n<p><code>site.config.ts</code> 还导出三个辅助函数，通常不需要修改：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>函数</th>\n<th>用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>isGiscusConfigured()</code></td>\n<td>检查 Giscus 必填字段是否完整，供评论组件决定是否加载</td>\n</tr>\n<tr>\n<td><code>requireSiteUrl()</code></td>\n<td>在生产构建开始时确认 <code>SITE_URL</code> 已设置</td>\n</tr>\n<tr>\n<td><code>withBasePath()</code></td>\n<td>为站内公开资源拼接规范化后的 <code>SITE_BASE</code>，外部 URL 保持不变</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"主题设计令牌\" tabindex=\"-1\">主题设计令牌 <a class=\"header-anchor\" href=\"#主题设计令牌\" aria-label=\"Permalink to “主题设计令牌”\">&#8203;</a></h2>\n<p>项目参考 shadcn-vue 的语义主题方式，将可复用视觉值集中放在 <code>src/.vitepress/theme/tailwind.css</code> 的 <code>@theme</code> 中。组件以 Tailwind utility 为主，不直接读取具体颜色或尺寸数值。唯一例外是 <code>ArticlePage.vue</code> 底部的 <code>&lt;style scoped&gt;</code>：它负责适配 VitePress 动态生成的 Markdown DOM，并直接读取相同的设计令牌。该适配层使用标准 CSS Nesting 将规则收拢在 <code>.article-content</code> 下，由现有 Tailwind CSS 4 + Vite 构建链处理，不需要额外的 nesting 插件或 PostCSS 配置。</p>\n<h3 id=\"颜色角色\" tabindex=\"-1\">颜色角色 <a class=\"header-anchor\" href=\"#颜色角色\" aria-label=\"Permalink to “颜色角色”\">&#8203;</a></h3>\n<p>Tailwind 默认颜色命名空间已经关闭。通用 surface 使用基础 token / <code>-foreground</code> 配对，保证背景和其上的内容一起变化：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>分组</th>\n<th>token</th>\n<th>用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>页面</td>\n<td><code>background</code> / <code>foreground</code></td>\n<td>页面画布与默认正文</td>\n</tr>\n<tr>\n<td>容器</td>\n<td><code>card</code> / <code>card-foreground</code>、<code>popover</code> / <code>popover-foreground</code></td>\n<td>内容卡片与浮层</td>\n</tr>\n<tr>\n<td>操作</td>\n<td><code>primary</code>、<code>secondary</code>、<code>accent</code> 及各自 <code>-foreground</code></td>\n<td>主要操作、次要表面、hover 与 active 状态</td>\n</tr>\n<tr>\n<td>辅助</td>\n<td><code>muted</code> / <code>muted-foreground</code></td>\n<td>低强调表面与辅助文字</td>\n</tr>\n<tr>\n<td>边界</td>\n<td><code>border</code>、<code>border-strong</code>、<code>ring</code></td>\n<td>容器边界、强边界与键盘焦点</td>\n</tr>\n<tr>\n<td>遮罩</td>\n<td><code>overlay</code> / <code>overlay-foreground</code></td>\n<td>dialog mask 及直接显示在 mask 上的内容</td>\n</tr>\n<tr>\n<td>状态</td>\n<td><code>info</code>、<code>success</code>、<code>important</code>、<code>warning</code>、<code>destructive</code>、<code>caution</code> 及各自 <code>-foreground</code></td>\n<td>容器、Alerts 与草稿提示</td>\n</tr>\n<tr>\n<td>代码领域</td>\n<td><code>code-background</code>、<code>code-card</code>、<code>code-muted-foreground</code>、<code>code-border</code>、<code>code-accent</code> 和代码行状态</td>\n<td>固定深色代码画布</td>\n</tr>\n</tbody>\n</table>\n<p>所有 <code>--color-*</code> 和阴影中的颜色必须使用 <code>oklab()</code>。亮色值定义在 <code>@theme</code>；<code>@utility theme-dark</code> 只覆盖确实不同的同名 token。根布局通过 <code>dark:theme-dark</code> 一次加载暗色值，组件继续使用 <code>bg-background</code>、<code>text-foreground</code>、<code>border-border</code> 等相同 utility。照片预览与搜索 dialog 的 mask 都使用 <code>overlay</code>；照片预览内直接落在 mask 上的图标和信息栏使用其通用配对 <code>overlay-foreground</code>，LIVE 标识和页面侧栏入口继续复用其它通用角色，不为单个组件建立专属色板。只有固定代码画布这类通用角色确实无法表达的功能才建立领域前缀，不能按页面或某次使用创建 <code>header-*</code>、<code>search-*</code> 一类颜色。</p>\n<h3 id=\"可维护尺度\" tabindex=\"-1\">可维护尺度 <a class=\"header-anchor\" href=\"#可维护尺度\" aria-label=\"Permalink to “可维护尺度”\">&#8203;</a></h3>\n<p>除颜色外，项目集中管理所有对博客有长期价值的设计尺度：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>类别</th>\n<th>namespace</th>\n<th>当前用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>字体与字重</td>\n<td><code>font-*</code>、<code>font-weight-*</code></td>\n<td>中文正文字体、代码字体和字体包真实提供的 <code>400</code> / <code>500</code></td>\n</tr>\n<tr>\n<td>字号与行高</td>\n<td><code>text-*</code>、<code>leading-*</code></td>\n<td>基础 type scale、文章标题/正文/章节、紧凑 label、callout 和代码行高</td>\n</tr>\n<tr>\n<td>字距</td>\n<td><code>tracking-*</code></td>\n<td>全局字距策略与 Live Photo 标识</td>\n</tr>\n<tr>\n<td>间距与尺寸</td>\n<td><code>spacing</code>、<code>spacing-page-*</code>、<code>spacing-header</code>、<code>spacing-control-*</code>、<code>spacing-side-rail-*</code></td>\n<td>基础 <code>4px</code> spacing scale、页面 gutter、页头、控件和侧轨位置</td>\n</tr>\n<tr>\n<td>圆角</td>\n<td><code>radius</code>、<code>radius-sm</code> 至 <code>radius-xl</code></td>\n<td>从单一基准派生的交互控件和容器圆角</td>\n</tr>\n<tr>\n<td>容器</td>\n<td><code>container-*</code></td>\n<td>列表内容、文章正文、三轨布局、导航、搜索和照片详情宽度</td>\n</tr>\n<tr>\n<td>响应式</td>\n<td><code>breakpoint-sm</code> 至 <code>breakpoint-xl</code></td>\n<td>项目实际使用的四个布局断点</td>\n</tr>\n<tr>\n<td>层级</td>\n<td><code>z-index-content</code>、<code>z-index-control</code>、<code>z-index-navigation</code></td>\n<td>内容附属项、浮动控件和导航浮层</td>\n</tr>\n<tr>\n<td>景深</td>\n<td><code>shadow-*</code>、<code>blur-*</code></td>\n<td>卡片、dialog、磨玻璃预览和代码 focus blur</td>\n</tr>\n<tr>\n<td>媒体</td>\n<td><code>aspect-*</code></td>\n<td>横图、竖图、混排图和文章封面比例</td>\n</tr>\n<tr>\n<td>动效</td>\n<td><code>duration-*</code>、<code>ease-*</code>、<code>animate-*</code></td>\n<td>默认过渡、即时缩放、慢速宽度变化、loading 和 Live Photo</td>\n</tr>\n</tbody>\n</table>\n<p>基础数值尺度使用 Tailwind 熟悉的 <code>sm</code>、<code>md</code>、<code>lg</code>；只有跨组件且用途稳定的值才使用 <code>page-gutter</code>、<code>side-rail-top</code> 这类语义名称。项目没有表单系统、统计图表或 dashboard sidebar，因此不会照搬 shadcn-vue 中没有实际消费者的 token；照片详情宽度属于稳定布局尺寸，可以保留 <code>container-photo-inspector</code>，但这不意味着照片功能需要独立颜色领域。</p>\n<h3 id=\"新增与修改规则\" tabindex=\"-1\">新增与修改规则 <a class=\"header-anchor\" href=\"#新增与修改规则\" aria-label=\"Permalink to “新增与修改规则”\">&#8203;</a></h3>\n<p>调整全站视觉时先修改已有 token。确需新增时，先确认它满足以下条件：在多个位置重复，或代表不会随组件名称变化的稳定语义；名称描述角色而非颜色值或当前页面；有源码消费者和必要的回归断言。surface 颜色必须补齐 <code>-foreground</code> 配对，独立领域内部也遵循 <code>background</code>、<code>foreground</code>、<code>card</code>、<code>muted</code>、<code>border</code>、<code>accent</code> 等一致后缀。</p>\n<p>视口 <code>calc()</code>、响应内容的 <code>minmax()</code> grid track、伪元素 <code>content</code> 和组合 transition property 依赖上下文，可以保留 arbitrary value。普通字号、字距、圆角、模糊、图片比例和动画已有命名尺度，不得再写 arbitrary value。不要使用 Tailwind 内置色板或任意硬编码颜色，也不要在文章 Markdown 适配层以外新增普通 CSS；<code>pnpm audit:styles</code> 会检查唯一 scoped CSS 例外、必需 namespace、颜色配对和旧 token 回归。</p>\n<h2 id=\"发布前检查\" tabindex=\"-1\">发布前检查 <a class=\"header-anchor\" href=\"#发布前检查\" aria-label=\"Permalink to “发布前检查”\">&#8203;</a></h2>\n<p>发布前至少确认：</p>\n<ul>\n<li><code>site.config.ts</code> 中的站点名称、简介、关键词和作者信息已替换。</li>\n<li>导航链接和 <code>homeSocials</code> 中没有无效占位地址。</li>\n<li>favicon 和 manifest 图标文件真实存在。</li>\n<li>workflow 的 <code>SITE_URL</code>、<code>SITE_BASE</code> 与 GitHub Pages 实际部署方式一致。</li>\n<li>不使用评论时 <code>giscus</code> 为 <code>null</code>；使用时全部字段来自目标仓库的 Giscus 配置。</li>\n<li>修改 <code>config.ts</code> 后，相关 Markdown、动态路由、SEO 或静态生成测试同步更新。</li>\n</ul>\n",
            "url": "https://ccbeango.github.io/blog/guide/site-configuration",
            "title": "配置站点信息",
            "summary": "完整说明站点身份、作者、导航、社交入口、评论，以及 VitePress 工程配置。",
            "date_modified": "2026-09-01T00:00:00.000Z",
            "date_published": "2026-09-01T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/writing-articles",
            "content_html": "<p>每篇文章都是 <code>src/posts</code> 下的 Markdown 文件。新增文件并填写 frontmatter 后，文章会自动进入列表、标签、归档、搜索和 feed，不需要再维护一份文章清单。</p>\n<h2 id=\"文件路径与公开-url\" tabindex=\"-1\">文件路径与公开 URL <a class=\"header-anchor\" href=\"#文件路径与公开-url\" aria-label=\"Permalink to “文件路径与公开 URL”\">&#8203;</a></h2>\n<p>文件相对 <code>src/posts</code> 的路径就是完整 slug：</p>\n<div class=\"language-text line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">text</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span>src/posts/guide/writing-articles.md -> /blog/guide/writing-articles</span></span>\n<span class=\"line\"><span>src/posts/travel/2026/sichuan.md     -> /blog/travel/2026/sichuan</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br></div></div><p>slug 支持多个路径段，但完整 slug 必须唯一。文章来源目录不会生成 <code>/posts</code> 公开路由。</p>\n<h2 id=\"frontmatter-示例\" tabindex=\"-1\">Frontmatter 示例 <a class=\"header-anchor\" href=\"#frontmatter-示例\" aria-label=\"Permalink to “Frontmatter 示例”\">&#8203;</a></h2>\n<div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">---</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">title</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">文章标题</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">date</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">2026-09-01</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">updated</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">2026-09-02</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">summary</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">列表与 feed 使用的摘要</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">description</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">SEO description，省略时使用 summary</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">keywords</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  - </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">VitePress</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  - </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">静态博客</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">featured</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">series</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  name</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">内容写作</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  order</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebar</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Bean Blog 使用手册</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebarOrder</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">tags</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  - </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">工程实践</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">draft</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">cover</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">/media/live-photo-sample-poster.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">canonical</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">https://example.com/original-article</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">---</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br><span class=\"line-number\">7</span><br><span class=\"line-number\">8</span><br><span class=\"line-number\">9</span><br><span class=\"line-number\">10</span><br><span class=\"line-number\">11</span><br><span class=\"line-number\">12</span><br><span class=\"line-number\">13</span><br><span class=\"line-number\">14</span><br><span class=\"line-number\">15</span><br><span class=\"line-number\">16</span><br><span class=\"line-number\">17</span><br><span class=\"line-number\">18</span><br><span class=\"line-number\">19</span><br><span class=\"line-number\">20</span><br><span class=\"line-number\">21</span><br></div></div><table tabindex=\"0\">\n<thead>\n<tr>\n<th>字段</th>\n<th>必填</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>title</code></td>\n<td>是</td>\n<td>非空文章标题</td>\n</tr>\n<tr>\n<td><code>date</code></td>\n<td>是</td>\n<td>可解析日期，建议使用 <code>YYYY-MM-DD</code></td>\n</tr>\n<tr>\n<td><code>updated</code></td>\n<td>否</td>\n<td>最近更新日期</td>\n</tr>\n<tr>\n<td><code>summary</code></td>\n<td>否</td>\n<td>首页、列表、搜索和 feed 摘要</td>\n</tr>\n<tr>\n<td><code>description</code></td>\n<td>否</td>\n<td>SEO description，省略时回退到 <code>summary</code></td>\n</tr>\n<tr>\n<td><code>keywords</code></td>\n<td>否</td>\n<td>SEO 与搜索关键词数组</td>\n</tr>\n<tr>\n<td><code>featured</code></td>\n<td>否</td>\n<td>是否进入首页“推荐阅读”，默认 <code>false</code></td>\n</tr>\n<tr>\n<td><code>series</code></td>\n<td>否</td>\n<td>自动系列侧栏信息</td>\n</tr>\n<tr>\n<td><code>tags</code></td>\n<td>否</td>\n<td>标签数组，会规范化、去重和计数</td>\n</tr>\n<tr>\n<td><code>draft</code></td>\n<td>否</td>\n<td>草稿状态，默认 <code>false</code></td>\n</tr>\n<tr>\n<td><code>cover</code></td>\n<td>否</td>\n<td><code>src/public</code> 下资源的根路径地址</td>\n</tr>\n<tr>\n<td><code>canonical</code></td>\n<td>否</td>\n<td>内容另有首发地址时使用的完整 URL</td>\n</tr>\n</tbody>\n</table>\n<p>无效日期、错误字段类型或重复 slug 会让配置加载失败，并在错误中指出对应文件和字段。</p>\n<h2 id=\"草稿与精选文章\" tabindex=\"-1\">草稿与精选文章 <a class=\"header-anchor\" href=\"#草稿与精选文章\" aria-label=\"Permalink to “草稿与精选文章”\">&#8203;</a></h2>\n<p><code>draft: true</code> 的文章只在开发环境中出现，并显示“草稿预览”。生产环境会从所有公开入口排除草稿，包括系列 sidebar、搜索、标签、归档、sitemap 和 feed。</p>\n<p><code>featured: true</code> 只控制文章是否进入首页“推荐阅读”候选，不会影响 <code>/blog</code> 列表中的可见性。首页按日期从新到旧最多展示 <code>siteConfig.site.featuredPostsLimit</code> 篇，默认上限为 5；超过上限的推荐文章仍可在 <code>/blog</code> 中访问。发布前将 <code>draft</code> 改为 <code>false</code>，再按需要设置 <code>featured</code>。</p>\n<p>仓库中的 <code>src/posts/guide/draft-preview.md</code> 是草稿过滤的可运行示例。</p>\n<h2 id=\"单系列侧栏\" tabindex=\"-1\">单系列侧栏 <a class=\"header-anchor\" href=\"#单系列侧栏\" aria-label=\"Permalink to “单系列侧栏”\">&#8203;</a></h2>\n<p>为文章添加同名 <code>series.name</code>，再使用正整数 <code>series.order</code> 控制顺序：</p>\n<div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">series</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  name</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">TypeScript 入门</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  order</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><p>同一系列不能重复使用相同 <code>order</code>。新增系列文章只需填写 frontmatter，不需要修改 <code>site.config.ts</code> 或手写 <code>themeConfig.sidebar</code>。</p>\n<h2 id=\"多分组侧栏\" tabindex=\"-1\">多分组侧栏 <a class=\"header-anchor\" href=\"#多分组侧栏\" aria-label=\"Permalink to “多分组侧栏”\">&#8203;</a></h2>\n<p>多个系列需要同时出现在左侧时，为它们设置相同 <code>sidebar</code>，并用 <code>sidebarOrder</code> 排列分组：</p>\n<div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#62687b;--shiki-dark:#818e99\"># “入门与配置”系列</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">series</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  name</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">入门与配置</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  order</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebar</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Bean Blog 使用手册</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebarOrder</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br></div></div><div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#62687b;--shiki-dark:#818e99\"># “内容写作”系列</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">series</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  name</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">内容写作</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  order</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebar</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Bean Blog 使用手册</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">  sidebarOrder</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">2</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br></div></div><p><code>sidebar</code> 是内部关联作用域，不会显示在页面中。<code>sidebar</code> 与 <code>sidebarOrder</code> 必须成对填写；同一系列的声明必须一致，同一 sidebar 中不同系列的 <code>sidebarOrder</code> 不能重复。</p>\n<p>系列 sidebar 在 VitePress 启动时生成。新增文章或修改标题、系列归属、sidebar 与顺序后需要重启开发服务。左侧系列导航用于切换手册文章，右侧本文目录用于定位当前文章标题，两者互不替代。</p>\n<h2 id=\"图片与静态资源\" tabindex=\"-1\">图片与静态资源 <a class=\"header-anchor\" href=\"#图片与静态资源\" aria-label=\"Permalink to “图片与静态资源”\">&#8203;</a></h2>\n<p>将公开资源放在 <code>src/public</code> 的明确子目录中，并在 Markdown 中使用根路径：</p>\n<div class=\"language-md line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">md</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">![</span><span style=\"--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline\">图片说明</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">](</span><span style=\"--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline\">/media/live-photo-sample-poster.png</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div><p>为图片提供有意义的 alt。普通正文图片由 VitePress 增加 <code>loading=&quot;lazy&quot;</code>；文章封面通过 frontmatter 的 <code>cover</code> 设置。</p>\n<h2 id=\"文章封面\" tabindex=\"-1\">文章封面 <a class=\"header-anchor\" href=\"#文章封面\" aria-label=\"Permalink to “文章封面”\">&#8203;</a></h2>\n<p>在 frontmatter 中填写 <code>cover</code>，即可在文章标题上方显示封面：</p>\n<div class=\"language-yaml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">yaml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#11782a;--shiki-dark:#85E89D\">cover</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">/media/live-photo-sample-poster.png</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div><p>封面文件放在 <code>src/public</code> 中，配置值使用从站点根路径开始的公开地址。封面下缘会渐隐到当前主题的页面背景，标题轻微上移到过渡区，让图片与文章信息形成连续头部；没有 <code>cover</code> 时不会生成空占位，也不会改变标题间距。点击封面可以进入与正文图片相同的照片预览，并支持缩放、拖动和照片信息查看。</p>\n<h2 id=\"发布一篇文章\" tabindex=\"-1\">发布一篇文章 <a class=\"header-anchor\" href=\"#发布一篇文章\" aria-label=\"Permalink to “发布一篇文章”\">&#8203;</a></h2>\n<ol>\n<li>在 <code>src/posts</code> 下创建 Markdown 文件。</li>\n<li>填写 <code>title</code>、<code>date</code> 和需要的可选 frontmatter。</li>\n<li>使用 <code>pnpm dev</code> 检查正文、目录、图片和窄屏布局。</li>\n<li>确认完整 slug、系列 <code>order</code> 与 <code>sidebarOrder</code> 没有冲突。</li>\n<li>将 <code>draft</code> 设置为 <code>false</code>，提交文章及引用的静态资源。</li>\n</ol>\n",
            "url": "https://ccbeango.github.io/blog/guide/writing-articles",
            "title": "创建和组织文章",
            "summary": "说明文章路径、frontmatter、草稿、精选文章、系列侧栏与静态资源的写法。",
            "date_modified": "2026-08-31T00:00:00.000Z",
            "date_published": "2026-08-31T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/markdown-extensions",
            "content_html": "<p>文章默认支持标准 Markdown、VitePress 官方扩展和少量已注册的 Vue 内容组件。本页中的示例就是当前主题的真实渲染结果，也由自动化测试直接验证。</p>\n<nav class=\"table-of-contents\"><ul><li><a href=\"#表格与任务列表\">表格与任务列表</a></li><li><a href=\"#数学公式\">数学公式</a></li><li><a href=\"#代码块\">代码块</a></li><li><a href=\"#custom-containers\">Custom Containers</a><ul><li><a href=\"#默认标题\">默认标题</a></li><li><a href=\"#自定义标题\">自定义标题</a></li></ul></li><li><a href=\"#github-alerts\">GitHub Alerts</a></li><li><a href=\"#code-groups\">Code Groups</a></li><li><a href=\"#代码行状态\">代码行状态</a></li><li><a href=\"#标题锚点与内部链接\">标题锚点与内部链接</a></li><li><a href=\"#普通图片\">普通图片</a></li></ul></nav>\n<h2 id=\"表格与任务列表\" tabindex=\"-1\">表格与任务列表 <a class=\"header-anchor\" href=\"#表格与任务列表\" aria-label=\"Permalink to “表格与任务列表”\">&#8203;</a></h2>\n<p>GFM 表格和任务列表无需额外配置：</p>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>能力</th>\n<th>构建阶段</th>\n<th>浏览器阶段</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>代码高亮</td>\n<td>Shiki</td>\n<td>复制按钮</td>\n</tr>\n<tr>\n<td>搜索</td>\n<td>索引生成</td>\n<td>本地匹配</td>\n</tr>\n<tr>\n<td>目录</td>\n<td>标题提取</td>\n<td>章节跟踪</td>\n</tr>\n</tbody>\n</table>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item enabled\"><input class=\"task-list-item-checkbox\" checked=\"\"type=\"checkbox\" id=\"task-item-2675660\"><label class=\"task-list-item-label\" for=\"task-item-2675660\"> 写作内容与公开路由解耦</label></li>\n<li class=\"task-list-item enabled\"><input class=\"task-list-item-checkbox\" checked=\"\"type=\"checkbox\" id=\"task-item-6357290\"><label class=\"task-list-item-label\" for=\"task-item-6357290\"> 生产环境排除草稿</label></li>\n<li class=\"task-list-item enabled\"><input class=\"task-list-item-checkbox\"type=\"checkbox\" id=\"task-item-7055325\"><label class=\"task-list-item-label\" for=\"task-item-7055325\"> 发布前替换正式域名</label></li>\n</ul>\n<h2 id=\"数学公式\" tabindex=\"-1\">数学公式 <a class=\"header-anchor\" href=\"#数学公式\" aria-label=\"Permalink to “数学公式”\">&#8203;</a></h2>\n<p>行内公式 <mjx-container v-pre class=\"MathJax\" jax=\"SVG\" style=\"direction: ltr; position: relative;\"><svg style=\"overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;\" xmlns=\"http://www.w3.org/2000/svg\" width=\"8.699ex\" height=\"2.072ex\" role=\"img\" focusable=\"false\" viewbox=\"0 -833.9 3845.1 915.9\" aria-hidden=\"true\"><g stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" transform=\"scale(1,-1)\"><g data-mml-node=\"math\"><g data-mml-node=\"mi\"><path data-c=\"1D438\" d=\"M492 213Q472 213 472 226Q472 230 477 250T482 285Q482 316 461 323T364 330H312Q311 328 277 192T243 52Q243 48 254 48T334 46Q428 46 458 48T518 61Q567 77 599 117T670 248Q680 270 683 272Q690 274 698 274Q718 274 718 261Q613 7 608 2Q605 0 322 0H133Q31 0 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H757Q764 676 764 669Q764 664 751 557T737 447Q735 440 717 440H705Q698 445 698 453L701 476Q704 500 704 528Q704 558 697 578T678 609T643 625T596 632T532 634H485Q397 633 392 631Q388 629 386 622Q385 619 355 499T324 377Q347 376 372 376H398Q464 376 489 391T534 472Q538 488 540 490T557 493Q562 493 565 493T570 492T572 491T574 487T577 483L544 351Q511 218 508 216Q505 213 492 213Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(1041.8,0)\"><path data-c=\"3D\" d=\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(2097.6,0)\"><path data-c=\"1D45A\" d=\"M21 287Q22 293 24 303T36 341T56 388T88 425T132 442T175 435T205 417T221 395T229 376L231 369Q231 367 232 367L243 378Q303 442 384 442Q401 442 415 440T441 433T460 423T475 411T485 398T493 385T497 373T500 364T502 357L510 367Q573 442 659 442Q713 442 746 415T780 336Q780 285 742 178T704 50Q705 36 709 31T724 26Q752 26 776 56T815 138Q818 149 821 151T837 153Q857 153 857 145Q857 144 853 130Q845 101 831 73T785 17T716 -10Q669 -10 648 17T627 73Q627 92 663 193T700 345Q700 404 656 404H651Q565 404 506 303L499 291L466 157Q433 26 428 16Q415 -11 385 -11Q372 -11 364 -4T353 8T350 18Q350 29 384 161L420 307Q423 322 423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 181Q151 335 151 342Q154 357 154 369Q154 405 129 405Q107 405 92 377T69 316T57 280Q55 278 41 278H27Q21 284 21 287Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"msup\" transform=\"translate(2975.6,0)\"><g data-mml-node=\"mi\"><path data-c=\"1D450\" d=\"M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mn\" transform=\"translate(466,363) scale(0.707)\"><path data-c=\"32\" d=\"M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z\" style=\"stroke-width: 3;\"></path></g></g></g></g></svg><mjx-assistive-mml unselectable=\"on\" display=\"inline\" style=\"top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></math></mjx-assistive-mml></mjx-container> 可以直接出现在段落中。块级公式使用成对的 <code>$$</code>，在窄屏中会限制在正文宽度内：</p>\n<mjx-container v-pre tabindex=\"0\" class=\"MathJax\" jax=\"SVG\" display=\"true\" style=\"direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;\"><svg style=\"overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;\" xmlns=\"http://www.w3.org/2000/svg\" width=\"31.579ex\" height=\"2.262ex\" role=\"img\" focusable=\"false\" viewbox=\"0 -750 13958 1000\" aria-hidden=\"true\"><g stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" transform=\"scale(1,-1)\"><g data-mml-node=\"math\"><g data-mml-node=\"mi\"><path data-c=\"1D447\" d=\"M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(704,0)\"><path data-c=\"28\" d=\"M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(1093,0)\"><path data-c=\"1D45B\" d=\"M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(1693,0)\"><path data-c=\"29\" d=\"M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(2359.8,0)\"><path data-c=\"3D\" d=\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(3415.6,0)\"><path data-c=\"1D447\" d=\"M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(4119.6,0)\"><path data-c=\"28\" d=\"M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(4508.6,0)\"><path data-c=\"1D45B\" d=\"M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(5330.8,0)\"><path data-c=\"2212\" d=\"M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mn\" transform=\"translate(6331,0)\"><path data-c=\"31\" d=\"M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(6831,0)\"><path data-c=\"29\" d=\"M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(7442.2,0)\"><path data-c=\"2B\" d=\"M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(8442.4,0)\"><path data-c=\"1D442\" d=\"M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(9205.4,0)\"><path data-c=\"28\" d=\"M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mn\" transform=\"translate(9594.4,0)\"><path data-c=\"31\" d=\"M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(10094.4,0)\"><path data-c=\"29\" d=\"M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(10761.2,0)\"><path data-c=\"3D\" d=\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(11817,0)\"><path data-c=\"1D442\" d=\"M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(12580,0)\"><path data-c=\"28\" d=\"M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mi\" transform=\"translate(12969,0)\"><path data-c=\"1D45B\" d=\"M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z\" style=\"stroke-width: 3;\"></path></g><g data-mml-node=\"mo\" transform=\"translate(13569,0)\"><path data-c=\"29\" d=\"M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z\" style=\"stroke-width: 3;\"></path></g></g></g></svg><mjx-assistive-mml unselectable=\"on\" display=\"block\" style=\"top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><mi>T</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>T</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container><h2 id=\"代码块\" tabindex=\"-1\">代码块 <a class=\"header-anchor\" href=\"#代码块\" aria-label=\"Permalink to “代码块”\">&#8203;</a></h2>\n<p>fenced code block 只需要声明语言。高亮、语言标签和复制行为均由 VitePress 与 Shiki 提供：</p>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">interface</span><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Post</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#c13617;--shiki-dark:#FFAB70\">  title</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">:</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#c13617;--shiki-dark:#FFAB70\">  slug</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">:</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#c13617;--shiki-dark:#FFAB70\">  draft</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">?:</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> boolean</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> published</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"--shiki-light:#c13617;--shiki-dark:#FFAB70\">posts</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">:</span><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Post</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">[]) </span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">=></span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> posts.</span><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">filter</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"--shiki-light:#c13617;--shiki-dark:#FFAB70\">post</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =></span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> !</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">post.draft);</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br><span class=\"line-number\">7</span><br></div></div><h2 id=\"custom-containers\" tabindex=\"-1\">Custom Containers <a class=\"header-anchor\" href=\"#custom-containers\" aria-label=\"Permalink to “Custom Containers”\">&#8203;</a></h2>\n<p>基础容器包括 <code>info</code>、<code>tip</code>、<code>warning</code>、<code>danger</code> 和原生可展开的 <code>details</code>。默认标题已经配置为中文。</p>\n<h3 id=\"默认标题\" tabindex=\"-1\">默认标题 <a class=\"header-anchor\" href=\"#默认标题\" aria-label=\"Permalink to “默认标题”\">&#8203;</a></h3>\n<div class=\"info custom-block\"><p class=\"custom-block-title custom-block-title-default\">信息</p>\n<p>适合补充背景、上下文或中性说明。</p>\n</div>\n<div class=\"tip custom-block\"><p class=\"custom-block-title custom-block-title-default\">提示</p>\n<p>适合给出建议、最佳实践或更便捷的做法。</p>\n</div>\n<div class=\"warning custom-block\"><p class=\"custom-block-title custom-block-title-default\">警告</p>\n<p>适合提醒需要留意但仍可继续的情况。</p>\n</div>\n<div class=\"danger custom-block\"><p class=\"custom-block-title custom-block-title-default\">危险</p>\n<p>适合说明可能造成数据丢失或不可逆影响的操作。</p>\n</div>\n<details class=\"details custom-block\"><summary>详细信息</summary>\n<p>这是浏览器原生的可展开内容，默认保持收起。</p>\n</details>\n<h3 id=\"自定义标题\" tabindex=\"-1\">自定义标题 <a class=\"header-anchor\" href=\"#自定义标题\" aria-label=\"Permalink to “自定义标题”\">&#8203;</a></h3>\n<p>在容器类型后直接添加标题：</p>\n<div class=\"danger custom-block\"><p class=\"custom-block-title\">停止</p>\n<p>危险区域，请先确认影响范围再继续。</p>\n</div>\n<details class=\"details custom-block\"><summary>点击查看代码</summary>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> message</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"Hello, VitePress!\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div></details>\n<h2 id=\"github-alerts\" tabindex=\"-1\">GitHub Alerts <a class=\"header-anchor\" href=\"#github-alerts\" aria-label=\"Permalink to “GitHub Alerts”\">&#8203;</a></h2>\n<p>GitHub 风格 Alerts 支持 <code>NOTE</code>、<code>TIP</code>、<code>IMPORTANT</code>、<code>WARNING</code> 和 <code>CAUTION</code>：</p>\n<div class=\"note custom-block github-alert\"><p class=\"custom-block-title\">备注</p>\n<p>用于补充读者应该了解的信息。</p>\n</div>\n<div class=\"tip custom-block github-alert\"><p class=\"custom-block-title\">提示</p>\n<p>用于帮助读者更顺利地完成操作。</p>\n</div>\n<div class=\"important custom-block github-alert\"><p class=\"custom-block-title\">重要</p>\n<p>用于强调完成目标所必需的信息。</p>\n</div>\n<div class=\"warning custom-block github-alert\"><p class=\"custom-block-title\">警告</p>\n<p>用于提示需要立即关注的风险。</p>\n</div>\n<div class=\"caution custom-block github-alert\"><p class=\"custom-block-title\">注意</p>\n<p>用于说明某个操作可能带来的负面后果。</p>\n</div>\n<h2 id=\"code-groups\" tabindex=\"-1\">Code Groups <a class=\"header-anchor\" href=\"#code-groups\" aria-label=\"Permalink to “Code Groups”\">&#8203;</a></h2>\n<p>Code Group 使用带标题的 fenced code block，标签切换由 VitePress 客户端处理：</p>\n<div class=\"vp-code-group\"><div class=\"tabs\"><input type=\"radio\" name=\"group-178\" id=\"tab-179\" checked><label data-title=\"pnpm\" for=\"tab-179\">pnpm</label><input type=\"radio\" name=\"group-178\" id=\"tab-180\" ><label data-title=\"npm\" for=\"tab-180\">npm</label></div><div class=\"blocks\">\n<div class=\"language-sh active line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">sh</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">pnpm</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> dev</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div><div class=\"language-sh line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">sh</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> run</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> dev</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br></div></div></div></div>\n<h2 id=\"代码行状态\" tabindex=\"-1\">代码行状态 <a class=\"header-anchor\" href=\"#代码行状态\" aria-label=\"Permalink to “代码行状态”\">&#8203;</a></h2>\n<p>行高亮、focus、diff、error 和 warning 使用 VitePress/Shiki 标记：</p>\n<div class=\"language-ts line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">ts</span><pre class=\"shiki shiki-themes github-light github-dark has-diff has-focused-lines has-highlighted\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> stable</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> true</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line highlighted has-focus\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> focused</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> true</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">; </span></span>\n<span class=\"line diff add\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> added</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"new\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">; </span></span>\n<span class=\"line diff remove\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> removed</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"old\"</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">; </span></span>\n<span class=\"line highlighted error\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> invalid</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> false</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">; </span></span>\n<span class=\"line highlighted warning\"><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">const</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> pending</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\"> =</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> true</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">; </span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br><span class=\"line-number\">6</span><br></div></div><h2 id=\"标题锚点与内部链接\" tabindex=\"-1\">标题锚点与内部链接 <a class=\"header-anchor\" href=\"#标题锚点与内部链接\" aria-label=\"Permalink to “标题锚点与内部链接”\">&#8203;</a></h2>\n<p>二级和三级标题由 VitePress 自动生成锚点。点击标题左侧的 <code>#</code> 或右侧本文目录后，URL hash 会更新，固定页头也不会遮挡目标标题。</p>\n<p>普通内部链接使用公开 <code>/blog</code> 地址。需要显示更完整的入口时，可以使用已注册的 <code>LinkedCard</code>：</p>\n<LinkedCard href=\"/blog/guide/writing-articles\" title=\"创建和组织文章\" description=\"查看路径、frontmatter、草稿和自动系列配置。\" /><p>不要在 Markdown 中任意引入 Vue 组件。新增内容组件时，应在 theme <code>enhanceApp</code> 中注册，并补充 renderer 和浏览器测试。</p>\n<h2 id=\"普通图片\" tabindex=\"-1\">普通图片 <a class=\"header-anchor\" href=\"#普通图片\" aria-label=\"Permalink to “普通图片”\">&#8203;</a></h2>\n<p>普通图片继续使用标准 Markdown 语法，并提供有意义的 alt：</p>\n<p><img src=\"/media/live-photo-sample-poster.png\" alt=\"Markdown 图片演示\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：Markdown 图片演示\" class=\"cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" width=\"960\" height=\"540\" loading=\"lazy\"></p>\n<p>VitePress 会为正文图片增加原生 <code>loading=&quot;lazy&quot;</code>。多张图片的组合方式见<a href=\"/blog/guide/image-layouts\">编排多图布局</a>。</p>\n",
            "url": "https://ccbeango.github.io/blog/guide/markdown-extensions",
            "title": "使用 Markdown 扩展",
            "summary": "通过可直接运行的示例使用 GFM、数学公式、代码块、容器、Alerts、Code Groups 和内容组件。",
            "date_modified": "2026-08-30T00:00:00.000Z",
            "date_published": "2026-08-30T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/image-layouts",
            "content_html": "<p>普通 Markdown 图片不需要特殊写法，会独占正文宽度并按文章顺序出现。</p>\n<p><img src=\"/media/live-photo-sample-poster.png\" alt=\"海边的横向风景\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：海边的横向风景\" class=\"cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" width=\"960\" height=\"540\" loading=\"lazy\"></p>\n<p>点击普通图片或多图布局中的任意图片，会先以全屏纯图模式完整展示原图。右上角的详情 icon 可以切换拍摄信息：宽屏时照片在左、信息在右，窄屏时改为上下排列。再次点击 icon 会恢复纯图模式，按 <code>Escape</code> 或右上角关闭按钮退出预览。</p>\n<p>桌面端可以把鼠标移到照片上滚动滚轮缩放，并在放大后按住左键拖动平移。双击照片或点击右上角出现的重置 icon 都会恢复原尺寸和居中位置；触控设备仍使用原生滚动，不会接管双指手势。</p>\n<p>拍摄信息在打开详情后才会按需读取，可能包含文件名、尺寸、拍摄时间、相机、镜头、焦距、光圈、快门和 ISO。没有 EXIF 的图片仍可正常预览，只会提示没有可读取的拍摄参数；GPS 不会被读取或展示。远程图片若要显示拍摄信息，需要允许博客域名通过 CORS 读取原文件。</p>\n<p>需要组合多张图片时，使用 VitePress 风格的三冒号 container 包围普通图片，并用空行分隔：</p>\n<div class=\"language-md line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">md</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">::: image-grid r73</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">![</span><span style=\"--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline\">横向图片</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">](</span><span style=\"--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline\">/media/live-photo-sample-poster.png</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">![</span><span style=\"--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline\">纵向图片</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">](</span><span style=\"--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline\">/media/live-photo-sample-poster.png</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:::</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br><span class=\"line-number\">4</span><br><span class=\"line-number\">5</span><br></div></div><p><code>image-grid</code> 是本博客注册的 VitePress Custom Container。构建时，VitePress 负责解析三冒号区块，博客插件再把合法内容增强为响应式布局。</p>\n<p>为减少仓库中的演示资源，本页所有格子重复使用同一张 <code>/media/live-photo-sample-poster.png</code>，通过不同布局裁切展示排版效果。实际文章可以为每个位置填写不同的本地路径或图床 URL。</p>\n<h2 id=\"可用布局\" tabindex=\"-1\">可用布局 <a class=\"header-anchor\" href=\"#可用布局\" aria-label=\"Permalink to “可用布局”\">&#8203;</a></h2>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>mode</th>\n<th>图片数量</th>\n<th>宽屏布局</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>landscape</code></td>\n<td>2 至 4 张</td>\n<td>等宽 <code>4:3</code> 横图；四张时为 <code>2×2</code> 宫格</td>\n</tr>\n<tr>\n<td><code>portrait</code></td>\n<td>2 至 4 张</td>\n<td>等宽 <code>3:4</code> 竖图；四张时为 <code>2×2</code> 宫格</td>\n</tr>\n<tr>\n<td><code>r73</code></td>\n<td>2 张</td>\n<td>左宽右窄，约 <code>7:3</code></td>\n</tr>\n<tr>\n<td><code>r37</code></td>\n<td>2 张</td>\n<td>左窄右宽，约 <code>3:7</code></td>\n</tr>\n<tr>\n<td><code>r64</code></td>\n<td>2 张</td>\n<td>左宽右窄，约 <code>64:36</code></td>\n</tr>\n<tr>\n<td><code>r46</code></td>\n<td>2 张</td>\n<td>左窄右宽，约 <code>36:64</code></td>\n</tr>\n</tbody>\n</table>\n<p>全部布局在窄屏下都会恢复为单列，并保留 Markdown 源顺序。</p>\n<h2 id=\"等宽横图与四张宫格\" tabindex=\"-1\">等宽横图与四张宫格 <a class=\"header-anchor\" href=\"#等宽横图与四张宫格\" aria-label=\"Permalink to “等宽横图与四张宫格”\">&#8203;</a></h2>\n<p><code>landscape</code> 支持两至四张图片。四张图片写在同一个 block 中即可形成 <code>2×2</code> 宫格，不需要新的 mode。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-2\" data-image-grid=\"landscape\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"山谷中的横向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：山谷中的横向风景\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"建筑与天空的横向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：建筑与天空的横向风景\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"山间拱门的横向裁切\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：山间拱门的横向裁切\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"海岸日落的横向裁切\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：海岸日落的横向裁切\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"等宽竖图\" tabindex=\"-1\">等宽竖图 <a class=\"header-anchor\" href=\"#等宽竖图\" aria-label=\"Permalink to “等宽竖图”\">&#8203;</a></h2>\n<p><code>portrait</code> 支持两至四张图片，所有容器使用 <code>3:4</code> 画幅。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-3\" data-image-grid=\"portrait\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-portrait\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"山间的纵向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：山间的纵向风景\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-portrait\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"光影中的纵向建筑\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：光影中的纵向建筑\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-portrait\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"海岸边的纵向景色\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：海岸边的纵向景色\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"七三布局\" tabindex=\"-1\">七三布局 <a class=\"header-anchor\" href=\"#七三布局\" aria-label=\"Permalink to “七三布局”\">&#8203;</a></h2>\n<p><code>r73</code> 让左图更宽、右图更窄，适合一张横图搭配一张竖图。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-[9fr_4fr]\" data-image-grid=\"r73\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-wide\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"作为主体的横向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：作为主体的横向风景\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-tall\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"作为补充的纵向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：作为补充的纵向风景\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"三七布局\" tabindex=\"-1\">三七布局 <a class=\"header-anchor\" href=\"#三七布局\" aria-label=\"Permalink to “三七布局”\">&#8203;</a></h2>\n<p><code>r37</code> 将窄图放在左侧、宽图放在右侧。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-[4fr_9fr]\" data-image-grid=\"r37\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-tall\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"左侧纵向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：左侧纵向风景\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-wide\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"右侧横向风景\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：右侧横向风景\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"六四布局\" tabindex=\"-1\">六四布局 <a class=\"header-anchor\" href=\"#六四布局\" aria-label=\"Permalink to “六四布局”\">&#8203;</a></h2>\n<p><code>r64</code> 的宽度差异更克制，左侧使用横向画幅，右侧使用纵向画幅。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-[16fr_9fr]\" data-image-grid=\"r64\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"左侧横向建筑\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：左侧横向建筑\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-portrait\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"右侧纵向建筑\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：右侧纵向建筑\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"四六布局\" tabindex=\"-1\">四六布局 <a class=\"header-anchor\" href=\"#四六布局\" aria-label=\"Permalink to “四六布局”\">&#8203;</a></h2>\n<p><code>r46</code> 是六四布局的镜像。</p>\n<figure class=\"not-prose my-8 grid w-full grid-cols-1 gap-3 sm:gap-4 sm:grid-cols-[9fr_16fr]\" data-image-grid=\"r46\">\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-portrait\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"左侧纵向建筑\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：左侧纵向建筑\" width=\"960\" height=\"540\"></p>\n<p class=\"m-0 min-w-0 overflow-hidden rounded-md bg-muted aspect-landscape\"><img src=\"/media/live-photo-sample-poster.png\" alt=\"右侧横向建筑\" class=\"m-0 block h-full w-full object-cover cursor-zoom-in focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring\" loading=\"lazy\" decoding=\"async\" data-photo-preview=\"\" role=\"button\" tabindex=\"0\" aria-label=\"预览图片：右侧横向建筑\" width=\"960\" height=\"540\"></p>\n</figure>\n<h2 id=\"输入约束\" tabindex=\"-1\">输入约束 <a class=\"header-anchor\" href=\"#输入约束\" aria-label=\"Permalink to “输入约束”\">&#8203;</a></h2>\n<p>block 中只允许普通 Markdown 图片和换行。比例布局固定为两张图片，等宽布局允许两至四张。以下情况会产生包含文件与行号的错误：</p>\n<ul>\n<li>mode 拼写错误或不受支持</li>\n<li>图片数量不符合规则</li>\n<li>block 中加入正文或其他元素</li>\n<li>嵌套另一个 <code>image-grid</code></li>\n<li>遗漏结束 <code>:::</code></li>\n</ul>\n",
            "url": "https://ccbeango.github.io/blog/guide/image-layouts",
            "title": "编排多图布局",
            "summary": "使用 VitePress 三冒号 image-grid 区块，在文章中编排横图、竖图、四张宫格和混合比例图片。",
            "date_modified": "2026-08-29T00:00:00.000Z",
            "date_published": "2026-08-29T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/live-photo",
            "content_html": "<p>Live Photo 在正文中首先是一张普通图片。读者点击左上角的 <code>LIVE</code> 后，动态片段才会在图片原位置播放；再次点击或播放结束后恢复静态首帧。点击首帧的其他区域会打开全屏照片预览，预览左上角同样可以播放 Live Photo，右上角的详情 icon 可以按需读取拍摄参数。</p>\n<h2 id=\"android-motion-photo-原文件\" tabindex=\"-1\">Android Motion Photo 原文件 <a class=\"header-anchor\" href=\"#android-motion-photo-原文件\" aria-label=\"Permalink to “Android Motion Photo 原文件”\">&#8203;</a></h2>\n<p>采用“JPEG 主图后追加 MP4”结构的 Android Motion Photo 可以直接引用原始 <code>.jpg</code>，不需要预先分离视频：</p>\n<div class=\"language-md line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">md</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">::: live-photo android</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">![</span><span style=\"--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline\">Android Motion Photo 演示</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">](</span><span style=\"--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline\">/live-images/android-motion-photo.jpg</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:::</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><LivePhoto mode=\"android\" poster=\"/live-images/android-motion-photo.jpg\" android-source=\"/live-images/android-motion-photo.jpg\" alt=\"Android Motion Photo 演示\" />\n<p>正文或照片预览中首次播放时，浏览器才会读取 JPEG 二进制、从文件末尾向前定位 MP4 的 <code>ftyp</code>，并创建 <code>video/mp4</code> Blob。各自停止后再次播放会复用各自的 Blob URL；关闭照片预览或离开文章时会释放对应资源。</p>\n<h2 id=\"使用独立-mp4\" tabindex=\"-1\">使用独立 MP4 <a class=\"header-anchor\" href=\"#使用独立-mp4\" aria-label=\"Permalink to “使用独立 MP4”\">&#8203;</a></h2>\n<p>已经分离好的静态首帧和浏览器可播放的 MP4 可以直接配对：</p>\n<div class=\"language-md line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">md</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">::: live-photo /media/live-photo-sample.mp4</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">![</span><span style=\"--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline\">独立 MP4 的静态首帧</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">](</span><span style=\"--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline\">/media/live-photo-sample-poster.png</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:::</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><LivePhoto poster=\"/media/live-photo-sample-poster.png\" video=\"/media/live-photo-sample.mp4\" alt=\"独立 MP4 的静态首帧\" />\n<p>独立 MP4 mode 在激活前只加载静态首帧，不提前请求视频。</p>\n<h2 id=\"资源要求\" tabindex=\"-1\">资源要求 <a class=\"header-anchor\" href=\"#资源要求\" aria-label=\"Permalink to “资源要求”\">&#8203;</a></h2>\n<p>同源文件建议放在 <code>src/public/live-images</code> 或 <code>src/public/media</code>。远程图片必须允许当前博客域名通过 CORS 读取响应；只能由 <code>&lt;img&gt;</code> 显示但不允许跨域读取的地址无法解析 Motion Photo，也无法在预览中读取 EXIF，但仍可作为普通静态图片查看。</p>\n<p>CDN、图片压缩服务和对象存储处理链必须保留 Android 原文件，不能重新编码 JPEG、删除文件尾部数据或只返回优化后的静态图。独立视频应使用目标浏览器可播放的 MP4 编码。</p>\n<p>当前 Android mode 不转码 HEVC、AV1 等浏览器不支持的编码，也不解析 Apple HEIC 与 MOV 文件对。解析失败或视频无法播放时，组件会恢复为普通静态图片。</p>\n<h2 id=\"区块语法\" tabindex=\"-1\">区块语法 <a class=\"header-anchor\" href=\"#区块语法\" aria-label=\"Permalink to “区块语法”\">&#8203;</a></h2>\n<p><code>live-photo</code> 是本博客注册的 VitePress Custom Container。区块内必须且只能包含一张普通 Markdown 图片，图片继续提供静态首帧、alt 和资源地址。</p>\n<p>开始行只能使用 <code>::: live-photo android</code> 或在 <code>live-photo</code> 后提供一个非空 MP4 地址。缺少图片、包含正文、嵌套 block 或遗漏结束 <code>:::</code> 都会在开发时报告文件与行号。旧的 HTML comment 写法不再解析。</p>\n",
            "url": "https://ccbeango.github.io/blog/guide/live-photo",
            "title": "使用 Live Photo",
            "summary": "使用独立 MP4 或 Android Motion Photo 原文件，在文章中提供按需播放的动态照片。",
            "date_modified": "2026-08-28T00:00:00.000Z",
            "date_published": "2026-08-28T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        },
        {
            "id": "https://ccbeango.github.io/blog/guide/deployment",
            "content_html": "<p>所有平台都安装同一份依赖、执行同一条构建命令，并发布 VitePress 的静态输出目录。</p>\n<h2 id=\"通用构建设置\" tabindex=\"-1\">通用构建设置 <a class=\"header-anchor\" href=\"#通用构建设置\" aria-label=\"Permalink to “通用构建设置”\">&#8203;</a></h2>\n<table tabindex=\"0\">\n<thead>\n<tr>\n<th>设置</th>\n<th>值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Install command</td>\n<td><code>pnpm install --frozen-lockfile</code></td>\n</tr>\n<tr>\n<td>Build command</td>\n<td><code>pnpm build</code></td>\n</tr>\n<tr>\n<td>Output directory</td>\n<td><code>src/.vitepress/dist</code></td>\n</tr>\n<tr>\n<td>Node.js</td>\n<td>22.12 或更高</td>\n</tr>\n<tr>\n<td>必需环境变量</td>\n<td><code>SITE_URL=https://你的域名</code></td>\n</tr>\n</tbody>\n</table>\n<p>生产构建缺少 <code>SITE_URL</code> 会失败，避免发布错误的 canonical、robots、sitemap 和 feed URL。</p>\n<p>本地验证当前 GitHub Pages 根站点时，可以直接使用已经写入 <code>package.json</code> 的命令：</p>\n<div class=\"language-powershell line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">powershell</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm build:local</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm preview</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br></div></div><p><code>build:local</code> 通过 <code>cross-env</code> 注入 <code>SITE_URL=https://username.github.io</code> 和 <code>SITE_BASE=/</code>，因此在 Windows、macOS 与 Linux 上行为一致。<code>pnpm build</code> 仍要求调用方显式提供发布环境变量。</p>\n<h2 id=\"github-pages\" tabindex=\"-1\">GitHub Pages <a class=\"header-anchor\" href=\"#github-pages\" aria-label=\"Permalink to “GitHub Pages”\">&#8203;</a></h2>\n<p>当前 workflow 位于 <code>.github/workflows/deploy.yml</code>，在 <code>master</code> 分支 push 或手动触发时构建并发布 <code>src/.vitepress/dist</code>。它直接声明当前根站点配置：</p>\n<div class=\"language-text line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">text</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span>SITE_URL=https://username.github.io</span></span>\n<span class=\"line\"><span>SITE_BASE=/</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br></div></div><p>workflow 使用 <code>github.repository_owner</code> 动态生成实际 <code>SITE_URL</code>。根站点要求 GitHub 仓库名为 <code>username.github.io</code>，其中 <code>username</code> 替换为仓库所有者，并在仓库 <code>Settings -&gt; Pages -&gt; Build and deployment</code> 中选择 <code>GitHub Actions</code>。普通仓库无法仅通过把 <code>SITE_BASE</code> 改为 <code>/</code> 占用用户根路径。</p>\n<p>如果继续使用普通仓库名，例如项目站点 <code>https://username.github.io/bean-blog/</code>，则需要同步修改 workflow：</p>\n<div class=\"language-text line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">text</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span>SITE_URL=https://username.github.io</span></span>\n<span class=\"line\"><span>SITE_BASE=/bean-blog/</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br></div></div><p>workflow 使用 GitHub Pages 官方 artifact 和 OIDC 部署，不需要个人 Access Token 或手工维护 <code>gh-pages</code> 分支。切换自定义域名后，把 <code>SITE_URL</code> 改为最终 HTTPS 域名；根路径部署时保持 <code>SITE_BASE=/</code>。</p>\n<h2 id=\"cloudflare-pages\" tabindex=\"-1\">Cloudflare Pages <a class=\"header-anchor\" href=\"#cloudflare-pages\" aria-label=\"Permalink to “Cloudflare Pages”\">&#8203;</a></h2>\n<ul>\n<li>Framework preset：None</li>\n<li>Build command：<code>pnpm build</code></li>\n<li>Build output directory：<code>src/.vitepress/dist</code></li>\n<li>Environment variables：设置 <code>SITE_URL</code>，子路径部署时再设置 <code>SITE_BASE</code></li>\n</ul>\n<p>绑定 custom domain 后，<code>SITE_URL</code> 必须与读者最终访问的 HTTPS origin 一致。</p>\n<h2 id=\"vercel\" tabindex=\"-1\">Vercel <a class=\"header-anchor\" href=\"#vercel\" aria-label=\"Permalink to “Vercel”\">&#8203;</a></h2>\n<ul>\n<li>Framework preset：Other</li>\n<li>Build command：<code>pnpm build</code></li>\n<li>Output directory：<code>src/.vitepress/dist</code></li>\n<li>Environment variables：为 Production 设置 <code>SITE_URL</code></li>\n</ul>\n<p>Vercel 根域部署通常不设置 <code>SITE_BASE</code>。如果 Preview deployment 也执行生产构建，需要为 Preview 提供对应绝对 URL。</p>\n<h2 id=\"netlify\" tabindex=\"-1\">Netlify <a class=\"header-anchor\" href=\"#netlify\" aria-label=\"Permalink to “Netlify”\">&#8203;</a></h2>\n<div class=\"language-toml line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">toml</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">[</span><span style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">build</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">command = </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"pnpm build\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">publish = </span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"src/.vitepress/dist\"</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><p>在 Site configuration 中设置 <code>SITE_URL</code>。使用子路径代理时，再设置带首尾 <code>/</code> 的 <code>SITE_BASE</code>。</p>\n<h2 id=\"发布检查\" tabindex=\"-1\">发布检查 <a class=\"header-anchor\" href=\"#发布检查\" aria-label=\"Permalink to “发布检查”\">&#8203;</a></h2>\n<div class=\"language-powershell line-numbers-mode\"><button title=\"复制代码\" data-copied=\"已复制\" class=\"copy\"></button><span class=\"lang\">powershell</span><pre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\" dir=\"ltr\" v-pre=\"\"><code><span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">$</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">env:</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">SITE_URL</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">=</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'https://username.github.io'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">$</span><span style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">env:</span><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">SITE_BASE</span><span style=\"--shiki-light:#c62739;--shiki-dark:#F97583\">=</span><span style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'/'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">pnpm check</span></span></code></pre>\n<div class=\"line-numbers-wrapper\" aria-hidden=\"true\"><span class=\"line-number\">1</span><br><span class=\"line-number\">2</span><br><span class=\"line-number\">3</span><br></div></div><p><code>pnpm check</code> 会生成资源，校验字体和样式边界，执行 lint、类型检查、单元测试、生产构建、静态产物检查和浏览器回归。</p>\n<p>完成后运行 <code>pnpm preview</code>，并确认以下地址可访问：</p>\n<ul>\n<li><code>/robots.txt</code> 与 <code>/sitemap.xml</code></li>\n<li><code>/rss.xml</code>、<code>/index.xml</code>、<code>/atom.xml</code> 与 <code>/feed.json</code></li>\n<li><code>/site.webmanifest</code> 和 favicon</li>\n<li><code>/blog</code>、文章详情、标签、归档和分页</li>\n</ul>\n<p>最后检查 canonical 使用正式域名、草稿没有进入公开产物，并在桌面与移动视口抽查目录、系列导航、代码和媒体内容。</p>\n",
            "url": "https://ccbeango.github.io/blog/guide/deployment",
            "title": "部署与发布",
            "summary": "配置 SITE_URL 与 SITE_BASE，并将静态产物部署到主流托管平台。",
            "date_modified": "2026-08-27T00:00:00.000Z",
            "date_published": "2026-08-27T00:00:00.000Z",
            "author": {
                "name": "Bean",
                "url": "https://ccbeango.github.io"
            }
        }
    ]
}