编辑文档
Starlight 内容编辑入门教程
Section titled “Starlight 内容编辑入门教程”本教程适合刚接触 Starlight 的文档作者,带你从零开始学会写页面、用组件、配导航。
一、先认识你的项目结构
Section titled “一、先认识你的项目结构”在开始写作之前,先了解一下 Starlight 项目的文件都放在哪里。你不需要记住所有文件,重点关注下面这几个就够了:
你的项目/├── astro.config.mjs # Astro 配置文件(包含 Starlight 集成和侧边栏配置)├── src/│ ├── content/│ │ ├── docs/ # ★ 你的所有文档页面都放在这里│ │ │ ├── guides/│ │ │ │ ├── 01-getting-started.md│ │ │ │ └── 02-advanced.md│ │ │ └── index.mdx│ │ ├── i18n/ # 可选:国际化翻译数据│ │ └── content.config.ts # 内容集合配置文件│ ├── assets/ # 图片、Logo 等资源│ └── components/ # 自定义组件└── public/ # 静态资源(字体、图标、PDF 等,不会被 Astro 处理)关键规则:src/content/docs/ 里的每一个 .md 或 .mdx 文件都会自动变成网站上的一个页面。用子文件夹来组织文件,就会自动生成对应的 URL 路径。
举个例子,文件结构这样放:
src/content/docs/├── hello-world.md → your-site.com/hello-world└── reference/ └── faq.md → your-site.com/reference/faq二、创建你的第一个页面
Section titled “二、创建你的第一个页面”在 src/content/docs/ 下新建一个 .md 文件,比如 my-first-page.md,然后写上下面的内容:
---title: 我的第一个页面description: 这是一个示例页面,用来学习 Starlight 的基本写法。---
这是页面的正文内容。你可以在这里写任何想说的话。注意:每个页面都必须在文件开头的 --- 之间提供一个 title(标题)。这个标题会显示在页面顶部、浏览器标签页和页面元数据中。
frontmatter 还能写什么?
Section titled “frontmatter 还能写什么?”title 是唯一必填的字段。其他常用字段包括:
---title: 页面标题 # 必填description: 页面的简短描述 # 用于 SEO 和搜索结果slug: custom-url # 自定义 URL(可选)editUrl: https://github.com/... # 编辑此页面的链接(可选)tableOfContents: false # 是否显示右侧目录(默认 true)---三、Markdown 基础写作
Section titled “三、Markdown 基础写作”Starlight 支持完整的 Markdown 语法。以下是你最常用的几种写法:
3.1 文本格式
Section titled “3.1 文本格式”这是 **粗体**,这是 *斜体*,这是 ~~删除线~~。这是 `行内代码`。3.2 标题
Section titled “3.2 标题”不要用 # 写一级标题。Starlight 会自动把 frontmatter 中的 title 作为页面的一级标题。你的正文应该从 ## 开始:
## 二级标题(会出现在右侧目录中)
### 三级标题(也会出现在目录中)
#### 四级标题(不会出现在目录中)3.3 链接与图片
Section titled “3.3 链接与图片”[链接文字](https://example.com)
图片放在 src/content/docs/ 旁边的位置,或者放在 src/assets/ 里都可以。图片描述(alt text)对屏幕阅读器很重要,不要省略。
3.4 旁白(Aside)
Section titled “3.4 旁白(Aside)”旁白用来在正文旁边显示辅助信息,是 Starlight 的一个特色功能。语法是用一对 ::: 包裹内容:
:::note这是一个普通提示。:::
:::tip这是一个小技巧。:::
:::caution注意!这里可能会踩坑。:::
:::danger危险!请谨慎操作。:::你还可以自定义标题和图标:
:::tip[你知道吗?]{icon="heart"}自定义标题和心形图标。:::建议:caution 和 danger 不要滥用。如果你发现自己频繁使用它们,可能说明内容需要重新组织一下。
3.5 引用和代码块
Section titled “3.5 引用和代码块”> 这是块引用,通常用来引用其他人的话。
```javascript// 代码块,开头指定语言const greeting = "Hello, Starlight!";```txt四、使用 MDX 和组件
Section titled “四、使用 MDX 和组件”当 Markdown 不够用的时候,可以把文件后缀改成 .mdx,就能在文档里使用组件了。
4.1 在 MDX 中使用内置组件
Section titled “4.1 在 MDX 中使用内置组件”Starlight 提供了许多内置组件,从 @astrojs/starlight/components 包导入即可:
---title: 使用组件---
import { Card, CardGrid, LinkCard, Tabs, TabItem } from '@astrojs/starlight/components';
<CardGrid> <LinkCard title="Starlight 官网" href="https://starlight.astro.build/" description="官方文档和指南" /> <LinkCard title="Astro 文档" href="https://docs.astro.build/" description="Astro 框架的完整文档" /></CardGrid>4.2 常用内置组件速查
Section titled “4.2 常用内置组件速查”| 组件 | 用途 | 简单示例 |
|---|---|---|
<Card> / <CardGrid> |
卡片布局 | <Card title="标题">内容</Card> |
<LinkCard> |
链接卡片 | <LinkCard title="..." href="..." /> |
<Tabs> / <TabItem> |
标签页切换 | <Tabs><TabItem label="Tab 1">...</TabItem></Tabs> |
<Steps> |
步骤列表 | <Steps><li>第一步</li></Steps> |
<Aside> |
旁白(等价于 :::) |
<Aside type="tip">...</Aside> |
<Badge> |
徽章标签 | <Badge text="New" variant="tip" /> |
<FileTree> |
文件树展示 | <FileTree><ul><li>src/</li></ul></FileTree> |
4.3 OreUI 交互组件:选择题和复选任务清单
Section titled “4.3 OreUI 交互组件:选择题和复选任务清单”本站提供基于 Astro 官方文档源码移植的交互组件,外观已适配 OreUI。可先打开交互组件示例体验选择、提交答案和勾选任务。
本站以 Spectrollay-OreUI/OreUI 为主体,沿用原有配色、按钮、面板和交互组件样式。全站样式通过 astro.config.mjs 的 customCss 引入 src/styles/oreui.css,选择题和复选任务清单的样式位于 src/components/tutorial/tutorial.css。
katorlys/OreUI 的 oreui-web@0.1.0-beta.1 依赖作为补充保留,仅按需使用组件样式,不全局加载整库。目前已复用其原生 Progress Bar,用于首次加载和站内页面跳转时的 LOADING 动画;后续按具体需要逐步采用其按钮等组件。引入时应限制作用范围,避免覆盖主体主题。第一库及交互逻辑来源采用 MIT 许可,第二库采用 MPL-2.0,来源与许可说明见 src/styles/vendor/oreui/README.md。
页面加载动画由 src/components/PageLoading.astro 和 Starlight 的 PageFrame 插槽统一接入,文档、首页和图集页面自动生效,无需逐页添加。LOADING 使用 public/B_Minecrafter.Reg(主标题).ttf,通过字体预加载和 document.fonts.load() 检查就绪状态:遮罩及进度条立即显示,文字在指定字体就绪后显示,避免备用字体闪烁;字体请求失败时使用备用字体并正常收起加载层。进度仅表示正在加载,不显示下载百分比,首次进入时使用不透明的全屏遮罩,加载完成后淡出;站内跳转时使用 65% 不透明度的背景遮罩,文字和进度条本身保持不透明,进入时淡入、完成后淡出。淡入为 180ms,淡出为 240ms,跨页面通过一次性的跳转标记延续遮罩类型。页内锚点、外部链接和新标签页操作不触发动画,减少动态效果偏好下停止持续推进和淡入淡出,无 JavaScript 时不显示遮罩。直接输出原始 HTML 的独立 Secret 页面保持原文件内容,不注入加载层。
跨页面加载层的连续衔接使用浏览器原生的跨文档 View Transitions 作为渐进增强:支持该接口且未开启“减少动态效果”时,旧页面的遮罩和文字快照会保留到新文档准备好,再对快照本身执行 240ms 淡出;进度条独立参与过渡,显示新页面中可更新的进度,加载完成时先填满,再与遮罩和文字同步淡出,避免冻结在旧快照中的中间进度;其他浏览器继续使用普通整页跳转和原有淡入淡出。该增强不接管路由、不复用文档 DOM,也不改变选择题等组件的脚本生命周期。字体就绪 promise 会通过 pagereveal 的 waitUntil() 纳入过渡,字体加载失败时仍能结束过渡。若浏览器报告过渡不可用或发生异常,页面会回退到普通加载流程。
这些组件需要在 .mdx 页面中使用。当前「编辑文档」仍是 .md 文件,因此这里的代码用于说明,实际交互放在示例页中。无需添加 client:load 等指令,也无需安装 React 或 Vue。
下面的导入路径适用于 src/content/docs/技术文档/文档站/ 下的 MDX 文件;放到其他目录时,需要按页面位置调整相对路径。
import MultipleChoice from '../../../../components/tutorial/MultipleChoice.astro';import Option from '../../../../components/tutorial/Option.astro';import Box from '../../../../components/tutorial/Box.astro';
<Box icon="question-mark">
## 哪个后缀支持导入组件?
<MultipleChoice> <Option> <span>.md</span> <span slot="feedback">普通 Markdown 不支持直接导入组件,再试一次。</span> </Option> <Option isCorrect> <span>.mdx</span> <span slot="feedback">回答正确,MDX 支持导入组件!</span> </Option></MultipleChoice>
</Box>MultipleChoice 是单选题容器;每个 Option 是一个选项,一道题应只为一个选项设置 isCorrect。选中选项后,「检查答案」按钮才会启用。提交后会显示结果,重新选择可再次作答。可选的 feedback 插槽用于填写该选项的解释,不填写时使用默认中文反馈。同一页面可以放多道题,选项分组互不影响。
复选任务清单
Section titled “复选任务清单”import Checklist from '../../../../components/tutorial/Checklist.astro';import Box from '../../../../components/tutorial/Box.astro';
<Box icon="check-list">
## 发布前检查
<Checklist key="publish-checks">
- [ ] 已设置页面标题。- [ ] 已检查图片和链接。- [ ] 已在本地预览。
</Checklist>
</Box>任务项使用 Markdown 的 - [ ] 语法,组件标签与任务列表之间保留空行。勾选状态按页面完整路径 + 清单 key保存在当前浏览器的 localStorage 中,刷新后会恢复;不会上传服务器,也不会跨浏览器同步。禁用 JavaScript 时清单保持不可交互。
同一页面上的每个清单必须使用不同且稳定的 key。改变页面路径或 key 会建立新的进度记录;改变某组任务数量会重置该组状态。避免重排任务后沿用原记录,因为勾选状态按任务顺序保存。
可以用 alternative 插槽提供另一组完成方式:
<Checklist key="review-method">
- [ ] 已自行检查文档。
<div slot="alternative">
- [ ] 已请维护者协助检查。
</div>
</Checklist>两组之间显示「或者」;任意一组全部勾选,存储逻辑就将这个清单判定为完成。当前组件没有额外显示全站教程进度条。
Box 用于包裹题目或任务清单,也可独立使用。icon 支持 question-mark(问题)、check-list(清单)和 puzzle-piece(练习)。组件源码位于 src/components/tutorial/,统一样式位于该目录的 tutorial.css,官方 MIT 许可和来源说明也保存在同目录。
4.4 组件样式冲突怎么办?
Section titled “4.4 组件样式冲突怎么办?”如果组件样式和 Starlight 默认的 Markdown 样式冲突,给组件加上 not-content 类就能禁用默认样式:
<div class="not-content"> <!-- 这里的内容不会应用 Starlight 的默认 Markdown 样式 --></div>五、侧边栏导航配置
Section titled “五、侧边栏导航配置”默认情况下,Starlight 会根据 src/content/docs/ 的文件结构自动生成侧边栏。如果需要手动控制,可以在 astro.config.mjs 中配置:
import starlight from '@astrojs/starlight';
export default defineConfig({ integrations: [ starlight({ sidebar: [ { label: '入门指南', items: [ { label: '快速开始', slug: 'guides/getting-started' }, { label: '进阶用法', slug: 'guides/advanced' }, ], }, { label: '参考资料', autogenerate: { directory: 'reference' }, }, ], }), ],});说明:
slug对应src/content/docs/下的文件路径(不含后缀名)autogenerate会自动扫描指定目录下的所有页面label是显示在侧边栏中的文字
六、自定义页面(进阶)
Section titled “六、自定义页面(进阶)”大多数情况下你只需要写 .md 或 .mdx 文件就够了。但如果需要完全自定义布局,可以在 src/pages/ 下创建 .astro 文件:
src/├── content/docs/ # 常规 Markdown 页面│ └── hello-world.md└── pages/ ├── custom.astro # 自定义页面 └── archived.html # 也可以放 HTML要在自定义页面中使用 Starlight 的布局和样式,用 <StarlightPage> 组件包裹内容即可。
列车战绩页面
Section titled “列车战绩页面”主页的“列车战绩”按钮进入 /train/,该页面不加入侧边栏。查询主页和玩家详情均隐藏页面左侧导航。玩家详情使用 /train/player/?name=玩家名,可以直接分享链接。
- 页面路由:
src/pages/train/index.astro、src/pages/train/player.astro。 - 共用界面:
src/components/TrainStats.astro;交互逻辑:src/lib/train-page.ts。 - 接口地址、指标名称和数值格式:
src/lib/train-api.ts。目前直接请求https://train.lista233.cn/的 JSON 接口,无须 Worker 代理。更换地址时,需要确保 HTTPS 可用,并允许网站域名跨域访问;本地测试也需要允许开发服务器的来源。 - 样式:
src/styles/train.css,只负责布局和站点主题衔接;按钮、标签页、表格、原生选择框、输入框、折叠区域等复用oreui-web。筛选框放在表格外,避免弹出菜单与滚动容器发生冲突。
累计榜默认每页显示 10 人、最低参赛 2 局。主页提供每页 10 / 20 / 50 人和最低 2 / 5 / 10 局的快捷选项;高级查询可输入自定义整数:每页人数 1–100,最低参赛 1–1000 局。这两个上限是页面侧限制。自定义值会加入快捷下拉中,并随 URL 保留,刷新和从详情返回均不会丢失。切换筛选条件回到第 1 页。累计榜和日统计直接使用后端 page / limit 分页,以及当前指标的 total / totalPages 显示总人数和总页数,不再额外请求下一页探测。页码越界时按接口总页数调整到最后一页;无数据时回到第 1 页。游玩时长榜不受最低参赛局数限制。误杀相关榜单按数值从高到低展示。日统计以接口返回日期为准,每日 04:00 划分统计日。
查询主页的“高级查询”复用 oreui-web/modal 的原生 dialog.ore-modal,可组合统计范围、排行指标、日期、每页人数和最低参赛局数;填写玩家名时改查个人战绩,隐藏不适用的排行条件。弹窗打开时带入当前条件,点击“查询”才提交并回到第 1 页;“重置”只修改弹窗中的条件,“取消”、Esc 或点击遮罩不会提交。日统计日期留空时由接口选择当前统计日。弹窗的表单布局在手机端改为单列,内容可纵向滚动。
Modal 居中在 src/styles/train.css 中通过 .train-page dialog.ore-modal { margin: auto; } 保持。生产构建中 OreUI 的组件样式层可能被 Starlight 的重置样式层覆盖,不能只依赖库中的 :where(dialog.ore-modal) 自动外边距。tests/train-modal.test.mjs 对构建后的静态页面验证深浅色及桌面、手机的居中和视口范围;构建后设置 PLAYWRIGHT_MODULE 为已安装 Playwright 的模块 URL,再运行该测试。
手机端隐藏次要表格列,点击玩家名进入详情。详情顶部为累计总览,下方为累计战绩和日统计;从日榜进入时保留日期。遇到同名多个账号,累计详情按 UUID 分开展示,而排行榜和日统计仍遵循接口按玩家名合并的口径。
玩家名输入框(普通查询、玩家详情和高级查询)复用 OreUI Dropdown 的菜单及选项样式,通过 src/components/TrainPlayerInput.astro 和 src/lib/train-suggestions.ts 补充输入联想交互。输入停止 200ms 后请求 /api/players/search?keyword=关键词&limit=20;关键词为空时不请求。包含匹配、忽略大小写、前缀优先和去重均由后端负责,前端按接口顺序展示,不再下载排行榜名称或自行过滤排序。total 大于返回名称数时提示继续输入缩小范围。后端名称缓存约 60 秒,搜到的玩家可能没有累计统计数据,这是接口的正常行为。支持点击、方向键与 Enter 选择,Esc 收起候选;再按 Esc 可关闭 Modal。菜单使用原生 Popover,避免表格或 Modal 裁切。切换输入、失焦、关闭弹窗或离开页面会取消待发和在途请求,旧结果不会覆盖新关键词或重新展开菜单。搜索失败或无匹配时仍可手动输入完整名字查询。玩家累计详情不传职业分页参数,继续展示全部职业。
数据在打开页面、切换条件或手动刷新时加载,不定时自动刷新。刷新失败保留已有内容,仅提示“刷新失败”。页面不保存玩家数据到本地持久缓存,不包含逐局记录、赛季趋势或自制图表。
七、常见问题速查
Section titled “七、常见问题速查”| 问题 | 解决方法 |
|---|---|
| 页面没有出现在侧边栏 | 检查文件是否在 src/content/docs/ 下 |
| 标题显示不对 | 确认 frontmatter 中有 title 字段 |
| 图片不显示 | 确认路径正确,图片描述(alt)不能为空 |
| 组件不工作 | 文件后缀必须是 .mdx,且组件需要 import |
| 想隐藏右侧目录 | frontmatter 中设置 tableOfContents: false |
写 Starlight 文档的核心就三件事:
- 在
src/content/docs/里创建.md或.mdx文件,每个文件就是一个页面 - 用 frontmatter 配置页面元数据,
title是必填的 - 需要交互组件时用
.mdx,从@astrojs/starlight/components导入即可
掌握了这些,你就可以开始愉快地写文档了!