mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
refactor(skills): 统一文档刷新技能入口
- 新增 gframework-doc-refresh 统一技能入口,并补齐模块扫描、证据顺序、模板与校验脚本 - 更新共享文档规范与模块映射,收口源码模块到 README、docs 和 ai-libs 的固定关联 - 删除旧 vitepress-* 公开技能定义,避免继续以文档类型拆分入口 - 同步 documentation-governance-and-refresh 的恢复点、风险和下一步
This commit is contained in:
parent
d836ec8027
commit
1239fb4651
52
.agents/skills/README.md
Normal file
52
.agents/skills/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# GFramework Skills
|
||||||
|
|
||||||
|
文档工作流的公开入口已统一为 `gframework-doc-refresh`。
|
||||||
|
|
||||||
|
## 公开入口
|
||||||
|
|
||||||
|
### `gframework-doc-refresh`
|
||||||
|
|
||||||
|
按源码模块驱动文档刷新,而不是按 `guide`、`tutorial`、`api` 等类型拆入口。
|
||||||
|
|
||||||
|
适用场景:
|
||||||
|
|
||||||
|
- 刷新某个模块的 landing page
|
||||||
|
- 复核专题页是否与源码、测试、README 一致
|
||||||
|
- 评估是否需要补 API reference 或教程
|
||||||
|
- 在 adoption path 不清晰时引入 `ai-libs/` 消费者接法作为补充证据
|
||||||
|
|
||||||
|
推荐调用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/gframework-doc-refresh <module>
|
||||||
|
```
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/gframework-doc-refresh Core
|
||||||
|
/gframework-doc-refresh Godot.SourceGenerators
|
||||||
|
/gframework-doc-refresh Cqrs
|
||||||
|
```
|
||||||
|
|
||||||
|
## 共享资源
|
||||||
|
|
||||||
|
- `_shared/DOCUMENTATION_STANDARDS.md`
|
||||||
|
- 统一的文档规则、证据顺序与验证要求
|
||||||
|
- `_shared/module-map.json`
|
||||||
|
- 机器可读的模块映射表
|
||||||
|
- `_shared/module-config.sh`
|
||||||
|
- 轻量 shell 辅助函数
|
||||||
|
|
||||||
|
## 内部资源
|
||||||
|
|
||||||
|
`gframework-doc-refresh/` 下包含:
|
||||||
|
|
||||||
|
- `references/`
|
||||||
|
- 模块选择、证据顺序、输出策略
|
||||||
|
- `templates/`
|
||||||
|
- landing page、专题页、API reference、教程模板
|
||||||
|
- `scripts/`
|
||||||
|
- 模块扫描与文档验证脚本
|
||||||
|
|
||||||
|
旧 `vitepress-*` skills 不再作为并列公开入口保留。
|
||||||
108
.agents/skills/_shared/DOCUMENTATION_STANDARDS.md
Normal file
108
.agents/skills/_shared/DOCUMENTATION_STANDARDS.md
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# GFramework 文档编写规范
|
||||||
|
|
||||||
|
本文件只保留跨模块稳定生效的写作与校验规则,不再维护容易失真的固定页面清单。
|
||||||
|
|
||||||
|
模块到源码、测试、README、`docs/zh-CN` 栏目以及 `ai-libs/` 参考入口的映射,统一以
|
||||||
|
`.agents/skills/_shared/module-map.json` 为准。
|
||||||
|
|
||||||
|
## 证据顺序
|
||||||
|
|
||||||
|
统一按以下顺序判断文档应写什么、删什么、保留什么:
|
||||||
|
|
||||||
|
1. 源码、公开 XML docs、`*.csproj`
|
||||||
|
2. 对应测试和 snapshot
|
||||||
|
3. 模块 `README.md`
|
||||||
|
4. 当前 `docs/zh-CN` 页面
|
||||||
|
5. `ai-libs/` 下已验证的消费者项目
|
||||||
|
6. 归档文档,仅在前述证据无法解释当前行为时回看
|
||||||
|
|
||||||
|
不要把旧文档互相抄写当成“更新”。
|
||||||
|
|
||||||
|
## 模块驱动规则
|
||||||
|
|
||||||
|
- 先按源码模块归一化输入,再决定落到 landing page、专题页、API reference、教程还是仅做校验。
|
||||||
|
- 如果用户给的是栏目名而不是源码模块名,先映射回模块;若仍有歧义,只给归一化建议,不直接生成文档。
|
||||||
|
- 文档栏目是派生输出,不是主输入源。
|
||||||
|
|
||||||
|
## `ai-libs/` 使用边界
|
||||||
|
|
||||||
|
`ai-libs/` 只用于补消费者视角证据:
|
||||||
|
|
||||||
|
- 验证真实接入目录结构
|
||||||
|
- 查最小 wiring、扩展点装配方式
|
||||||
|
- 给 adoption path 提供端到端例子
|
||||||
|
|
||||||
|
不要用 `ai-libs/` 覆盖以下事实:
|
||||||
|
|
||||||
|
- 公共 API 契约
|
||||||
|
- 当前版本支持范围
|
||||||
|
- Source Generator 诊断与生成语义
|
||||||
|
|
||||||
|
如果 `ai-libs/` 与当前源码或测试冲突,以当前仓库实现为准,并在文档里写明迁移或兼容边界。
|
||||||
|
|
||||||
|
## Markdown 规则
|
||||||
|
|
||||||
|
### 泛型与 HTML 转义
|
||||||
|
|
||||||
|
代码块外出现泛型或 XML 标签时必须转义:
|
||||||
|
|
||||||
|
- `List<T>`
|
||||||
|
- `Result<TValue, TError>`
|
||||||
|
- `<summary>`
|
||||||
|
- `<param>`
|
||||||
|
|
||||||
|
### Frontmatter
|
||||||
|
|
||||||
|
每个文档都必须包含合法 frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 文档标题
|
||||||
|
description: 1-2 句话描述当前页面解决什么问题
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码块
|
||||||
|
|
||||||
|
- 始终标注语言,如 `csharp`、`bash`、`json`
|
||||||
|
- 示例只保留当前实现可追溯的最小路径
|
||||||
|
- 必要时写中文注释解释接入原因或边界,不要堆砌与代码同步无关的注释
|
||||||
|
|
||||||
|
### 链接
|
||||||
|
|
||||||
|
- 只链接到当前仓库真实存在的页面
|
||||||
|
- 站内链接优先使用 `/zh-CN/...` 形式
|
||||||
|
- 如果文档站不允许跳出 `docs/` 根目录,就不要把仓库 README 写成站内链接
|
||||||
|
|
||||||
|
## 输出优先级
|
||||||
|
|
||||||
|
统一按以下顺序决定产出:
|
||||||
|
|
||||||
|
1. 先修模块 README、landing page 与 adoption path
|
||||||
|
2. 再修失真的专题页
|
||||||
|
3. 再补 API reference
|
||||||
|
4. 最后才补教程
|
||||||
|
|
||||||
|
## 验证清单
|
||||||
|
|
||||||
|
- [ ] frontmatter 正确
|
||||||
|
- [ ] 代码块语言标记齐全
|
||||||
|
- [ ] 泛型和 XML 标签已转义
|
||||||
|
- [ ] 站内链接存在
|
||||||
|
- [ ] 示例与当前实现一致
|
||||||
|
- [ ] `ai-libs/` 只作为消费者接入参考,没有覆盖源码契约
|
||||||
|
|
||||||
|
## 验证工具
|
||||||
|
|
||||||
|
统一复用 `gframework-doc-refresh/scripts/` 下的校验脚本:
|
||||||
|
|
||||||
|
- `validate-frontmatter.sh`
|
||||||
|
- `validate-links.sh`
|
||||||
|
- `validate-code-blocks.sh`
|
||||||
|
- `validate-all.sh`
|
||||||
|
|
||||||
|
需要站点级验证时,执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd docs && bun run build
|
||||||
|
```
|
||||||
256
.agents/skills/_shared/module-config.sh
Normal file
256
.agents/skills/_shared/module-config.sh
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 共享的模块配置
|
||||||
|
# 机器可读映射以 .agents/skills/_shared/module-map.json 为准。
|
||||||
|
|
||||||
|
normalize_module() {
|
||||||
|
local INPUT
|
||||||
|
INPUT="$(echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr '_' '-')"
|
||||||
|
|
||||||
|
case "$INPUT" in
|
||||||
|
core|core-runtime|runtime-core|core-module)
|
||||||
|
echo "Core"
|
||||||
|
;;
|
||||||
|
core.abstractions|core-abstractions)
|
||||||
|
echo "Core.Abstractions"
|
||||||
|
;;
|
||||||
|
core.sourcegenerators|core-source-generators|core-sourcegenerators)
|
||||||
|
echo "Core.SourceGenerators"
|
||||||
|
;;
|
||||||
|
core.sourcegenerators.abstractions|core-source-generators-abstractions)
|
||||||
|
echo "Core.SourceGenerators.Abstractions"
|
||||||
|
;;
|
||||||
|
game|game-runtime|runtime-game|game-module)
|
||||||
|
echo "Game"
|
||||||
|
;;
|
||||||
|
game.abstractions|game-abstractions)
|
||||||
|
echo "Game.Abstractions"
|
||||||
|
;;
|
||||||
|
game.sourcegenerators|game-source-generators)
|
||||||
|
echo "Game.SourceGenerators"
|
||||||
|
;;
|
||||||
|
godot|godot-runtime|runtime-godot|godot-module)
|
||||||
|
echo "Godot"
|
||||||
|
;;
|
||||||
|
godot.sourcegenerators|godot-source-generators|godot-generators)
|
||||||
|
echo "Godot.SourceGenerators"
|
||||||
|
;;
|
||||||
|
godot.sourcegenerators.abstractions|godot-source-generators-abstractions)
|
||||||
|
echo "Godot.SourceGenerators.Abstractions"
|
||||||
|
;;
|
||||||
|
cqrs|mediator|cqrs-module)
|
||||||
|
echo "Cqrs"
|
||||||
|
;;
|
||||||
|
cqrs.abstractions|cqrs-abstractions)
|
||||||
|
echo "Cqrs.Abstractions"
|
||||||
|
;;
|
||||||
|
cqrs.sourcegenerators|cqrs-source-generators)
|
||||||
|
echo "Cqrs.SourceGenerators"
|
||||||
|
;;
|
||||||
|
ecs|ecs.arch|ecs-arch)
|
||||||
|
echo "Ecs.Arch"
|
||||||
|
;;
|
||||||
|
ecs.arch.abstractions|ecs-arch-abstractions)
|
||||||
|
echo "Ecs.Arch.Abstractions"
|
||||||
|
;;
|
||||||
|
sourcegenerators.common|source-generators-common)
|
||||||
|
echo "SourceGenerators.Common"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
get_all_modules() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Core
|
||||||
|
Core.Abstractions
|
||||||
|
Core.SourceGenerators
|
||||||
|
Core.SourceGenerators.Abstractions
|
||||||
|
Game
|
||||||
|
Game.Abstractions
|
||||||
|
Game.SourceGenerators
|
||||||
|
Godot
|
||||||
|
Godot.SourceGenerators
|
||||||
|
Godot.SourceGenerators.Abstractions
|
||||||
|
Cqrs
|
||||||
|
Cqrs.Abstractions
|
||||||
|
Cqrs.SourceGenerators
|
||||||
|
Ecs.Arch
|
||||||
|
Ecs.Arch.Abstractions
|
||||||
|
SourceGenerators.Common
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
is_valid_module() {
|
||||||
|
normalize_module "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_source_dirs() {
|
||||||
|
local MODULE
|
||||||
|
MODULE="$(normalize_module "$1")" || return 1
|
||||||
|
|
||||||
|
case "$MODULE" in
|
||||||
|
Core)
|
||||||
|
echo "GFramework.Core"
|
||||||
|
;;
|
||||||
|
Core.Abstractions)
|
||||||
|
echo "GFramework.Core.Abstractions"
|
||||||
|
;;
|
||||||
|
Core.SourceGenerators)
|
||||||
|
echo "GFramework.Core.SourceGenerators"
|
||||||
|
;;
|
||||||
|
Core.SourceGenerators.Abstractions)
|
||||||
|
echo "GFramework.Core.SourceGenerators.Abstractions"
|
||||||
|
;;
|
||||||
|
Game)
|
||||||
|
echo "GFramework.Game"
|
||||||
|
;;
|
||||||
|
Game.Abstractions)
|
||||||
|
echo "GFramework.Game.Abstractions"
|
||||||
|
;;
|
||||||
|
Game.SourceGenerators)
|
||||||
|
echo "GFramework.Game.SourceGenerators"
|
||||||
|
;;
|
||||||
|
Godot)
|
||||||
|
echo "GFramework.Godot"
|
||||||
|
;;
|
||||||
|
Godot.SourceGenerators)
|
||||||
|
echo "GFramework.Godot.SourceGenerators"
|
||||||
|
;;
|
||||||
|
Godot.SourceGenerators.Abstractions)
|
||||||
|
echo "GFramework.Godot.SourceGenerators.Abstractions"
|
||||||
|
;;
|
||||||
|
Cqrs)
|
||||||
|
echo "GFramework.Cqrs"
|
||||||
|
;;
|
||||||
|
Cqrs.Abstractions)
|
||||||
|
echo "GFramework.Cqrs.Abstractions"
|
||||||
|
;;
|
||||||
|
Cqrs.SourceGenerators)
|
||||||
|
echo "GFramework.Cqrs.SourceGenerators"
|
||||||
|
;;
|
||||||
|
Ecs.Arch)
|
||||||
|
echo "GFramework.Ecs.Arch"
|
||||||
|
;;
|
||||||
|
Ecs.Arch.Abstractions)
|
||||||
|
echo "GFramework.Ecs.Arch.Abstractions"
|
||||||
|
;;
|
||||||
|
SourceGenerators.Common)
|
||||||
|
echo "GFramework.SourceGenerators.Common"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
get_test_projects() {
|
||||||
|
local MODULE
|
||||||
|
MODULE="$(normalize_module "$1")" || return 1
|
||||||
|
|
||||||
|
case "$MODULE" in
|
||||||
|
Core|Core.Abstractions)
|
||||||
|
echo "GFramework.Core.Tests/GFramework.Core.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Core.SourceGenerators|Core.SourceGenerators.Abstractions|Game.SourceGenerators|Cqrs.SourceGenerators|SourceGenerators.Common)
|
||||||
|
echo "GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Game|Game.Abstractions)
|
||||||
|
echo "GFramework.Game.Tests/GFramework.Game.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Godot)
|
||||||
|
echo "GFramework.Godot.Tests/GFramework.Godot.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Godot.SourceGenerators|Godot.SourceGenerators.Abstractions)
|
||||||
|
echo "GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Cqrs|Cqrs.Abstractions)
|
||||||
|
echo "GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj"
|
||||||
|
;;
|
||||||
|
Ecs.Arch|Ecs.Arch.Abstractions)
|
||||||
|
echo "GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
get_readme_paths() {
|
||||||
|
local MODULE
|
||||||
|
MODULE="$(normalize_module "$1")" || return 1
|
||||||
|
|
||||||
|
case "$MODULE" in
|
||||||
|
Core)
|
||||||
|
echo "GFramework.Core/README.md"
|
||||||
|
;;
|
||||||
|
Core.Abstractions)
|
||||||
|
echo "GFramework.Core.Abstractions/README.md"
|
||||||
|
;;
|
||||||
|
Core.SourceGenerators)
|
||||||
|
echo "GFramework.Core.SourceGenerators/README.md"
|
||||||
|
;;
|
||||||
|
Game)
|
||||||
|
echo "GFramework.Game/README.md"
|
||||||
|
;;
|
||||||
|
Game.Abstractions)
|
||||||
|
echo "GFramework.Game.Abstractions/README.md"
|
||||||
|
;;
|
||||||
|
Game.SourceGenerators)
|
||||||
|
echo "GFramework.Game.SourceGenerators/README.md"
|
||||||
|
;;
|
||||||
|
Godot)
|
||||||
|
echo "GFramework.Godot/README.md"
|
||||||
|
;;
|
||||||
|
Godot.SourceGenerators)
|
||||||
|
echo "GFramework.Godot.SourceGenerators/README.md"
|
||||||
|
;;
|
||||||
|
Cqrs)
|
||||||
|
echo "GFramework.Cqrs/README.md"
|
||||||
|
;;
|
||||||
|
Cqrs.Abstractions)
|
||||||
|
echo "GFramework.Cqrs.Abstractions/README.md"
|
||||||
|
;;
|
||||||
|
Cqrs.SourceGenerators)
|
||||||
|
echo "GFramework.Cqrs.SourceGenerators/README.md"
|
||||||
|
;;
|
||||||
|
Ecs.Arch)
|
||||||
|
echo "GFramework.Ecs.Arch/README.md"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
infer_module_from_namespace() {
|
||||||
|
local NAMESPACE="$1"
|
||||||
|
|
||||||
|
if [[ "$NAMESPACE" == GFramework.Core.SourceGenerators.Abstractions* ]]; then
|
||||||
|
echo "Core.SourceGenerators.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Core.SourceGenerators* ]]; then
|
||||||
|
echo "Core.SourceGenerators"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Core.Abstractions* ]]; then
|
||||||
|
echo "Core.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Core* ]]; then
|
||||||
|
echo "Core"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Game.SourceGenerators* ]]; then
|
||||||
|
echo "Game.SourceGenerators"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Game.Abstractions* ]]; then
|
||||||
|
echo "Game.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Game* ]]; then
|
||||||
|
echo "Game"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Godot.SourceGenerators.Abstractions* ]]; then
|
||||||
|
echo "Godot.SourceGenerators.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Godot.SourceGenerators* ]]; then
|
||||||
|
echo "Godot.SourceGenerators"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Godot* ]]; then
|
||||||
|
echo "Godot"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Cqrs.SourceGenerators* ]]; then
|
||||||
|
echo "Cqrs.SourceGenerators"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Cqrs.Abstractions* ]]; then
|
||||||
|
echo "Cqrs.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Cqrs* ]]; then
|
||||||
|
echo "Cqrs"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Ecs.Arch.Abstractions* ]]; then
|
||||||
|
echo "Ecs.Arch.Abstractions"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.Ecs.Arch* ]]; then
|
||||||
|
echo "Ecs.Arch"
|
||||||
|
elif [[ "$NAMESPACE" == GFramework.SourceGenerators.Common* ]]; then
|
||||||
|
echo "SourceGenerators.Common"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
434
.agents/skills/_shared/module-map.json
Normal file
434
.agents/skills/_shared/module-map.json
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"description": "Canonical documentation refresh module map for GFramework skills.",
|
||||||
|
"modules": {
|
||||||
|
"Core": {
|
||||||
|
"aliases": ["core", "core-runtime", "runtime-core", "core module"],
|
||||||
|
"source_paths": ["GFramework.Core"],
|
||||||
|
"project_file": "GFramework.Core/GFramework.Core.csproj",
|
||||||
|
"test_projects": ["GFramework.Core.Tests/GFramework.Core.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Core/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/core/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/core/architecture.md",
|
||||||
|
"docs/zh-CN/core/context.md",
|
||||||
|
"docs/zh-CN/core/lifecycle.md",
|
||||||
|
"docs/zh-CN/core/events.md",
|
||||||
|
"docs/zh-CN/core/property.md",
|
||||||
|
"docs/zh-CN/core/logging.md",
|
||||||
|
"docs/zh-CN/core/state-management.md",
|
||||||
|
"docs/zh-CN/core/coroutine.md"
|
||||||
|
],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/getting-started/quick-start.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": [
|
||||||
|
"ai-libs/CoreGrid/CoreGrid.csproj",
|
||||||
|
"ai-libs/CoreGrid/global",
|
||||||
|
"ai-libs/CoreGrid/docs"
|
||||||
|
],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"Architecture|RegisterModel|RegisterSystem|BindableProperty|EventBus\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Core.Abstractions": {
|
||||||
|
"aliases": ["core.abstractions", "core-abstractions", "core abstractions"],
|
||||||
|
"source_paths": ["GFramework.Core.Abstractions"],
|
||||||
|
"project_file": "GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.Core.Tests/GFramework.Core.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Core.Abstractions/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/abstractions/core-abstractions.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/core/index.md",
|
||||||
|
"docs/zh-CN/core/architecture.md",
|
||||||
|
"docs/zh-CN/core/context.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/CoreGrid.csproj"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Core\\.Abstractions|IArchitecture|IModel|ISystem\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Core.SourceGenerators": {
|
||||||
|
"aliases": [
|
||||||
|
"core.sourcegenerators",
|
||||||
|
"core-sourcegenerators",
|
||||||
|
"core-source-generators",
|
||||||
|
"core source generators"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Core.SourceGenerators"],
|
||||||
|
"project_file": "GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj",
|
||||||
|
"test_projects": ["GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Core.SourceGenerators/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/source-generators/context-aware-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/context-get-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/priority-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/logging-generator.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global", "ai-libs/CoreGrid/scripts"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"ContextAware|ContextGet|Priority|GeneratedLogger|Log\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Core.SourceGenerators.Abstractions": {
|
||||||
|
"aliases": [
|
||||||
|
"core.sourcegenerators.abstractions",
|
||||||
|
"core-source-generators-abstractions",
|
||||||
|
"core source generators abstractions"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Core.SourceGenerators.Abstractions"],
|
||||||
|
"project_file": "GFramework.Core.SourceGenerators.Abstractions/GFramework.Core.SourceGenerators.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": [],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/source-generators/context-aware-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/context-get-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/priority-generator.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Core\\.SourceGenerators\\.Abstractions|\\[ContextAware\\]|\\[Priority\\]\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Game": {
|
||||||
|
"aliases": ["game", "game-runtime", "runtime-game", "game module"],
|
||||||
|
"source_paths": ["GFramework.Game"],
|
||||||
|
"project_file": "GFramework.Game/GFramework.Game.csproj",
|
||||||
|
"test_projects": ["GFramework.Game.Tests/GFramework.Game.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Game/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/game/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/game/scene.md",
|
||||||
|
"docs/zh-CN/game/ui.md",
|
||||||
|
"docs/zh-CN/game/data.md",
|
||||||
|
"docs/zh-CN/game/storage.md",
|
||||||
|
"docs/zh-CN/game/serialization.md",
|
||||||
|
"docs/zh-CN/game/setting.md",
|
||||||
|
"docs/zh-CN/game/config-system.md"
|
||||||
|
],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/getting-started/quick-start.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": [
|
||||||
|
"ai-libs/CoreGrid/global",
|
||||||
|
"ai-libs/CoreGrid/scenes",
|
||||||
|
"ai-libs/CoreGrid/addons"
|
||||||
|
],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"SceneRouter|UiRouter|Setting|Storage|Serialization|Config\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Game.Abstractions": {
|
||||||
|
"aliases": ["game.abstractions", "game-abstractions", "game abstractions"],
|
||||||
|
"source_paths": ["GFramework.Game.Abstractions"],
|
||||||
|
"project_file": "GFramework.Game.Abstractions/GFramework.Game.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.Game.Tests/GFramework.Game.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Game.Abstractions/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/abstractions/game-abstractions.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/game/index.md",
|
||||||
|
"docs/zh-CN/game/scene.md",
|
||||||
|
"docs/zh-CN/game/ui.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global", "ai-libs/CoreGrid/scenes"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"ISceneFactory|ISceneRoot|UiInteractionProfile|IUiRoot\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Game.SourceGenerators": {
|
||||||
|
"aliases": [
|
||||||
|
"game.sourcegenerators",
|
||||||
|
"game-source-generators",
|
||||||
|
"game source generators"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Game.SourceGenerators"],
|
||||||
|
"project_file": "GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj",
|
||||||
|
"test_projects": ["GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Game.SourceGenerators/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/source-generators/auto-scene-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/auto-ui-page-generator.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/game/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/scenes", "ai-libs/CoreGrid/addons"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"AutoScene|AutoUiPage|SceneRouter|UiRouter\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Godot": {
|
||||||
|
"aliases": ["godot", "godot-runtime", "runtime-godot", "godot module"],
|
||||||
|
"source_paths": ["GFramework.Godot"],
|
||||||
|
"project_file": "GFramework.Godot/GFramework.Godot.csproj",
|
||||||
|
"test_projects": ["GFramework.Godot.Tests/GFramework.Godot.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Godot/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/godot/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/godot/architecture.md",
|
||||||
|
"docs/zh-CN/godot/scene.md",
|
||||||
|
"docs/zh-CN/godot/ui.md",
|
||||||
|
"docs/zh-CN/godot/storage.md",
|
||||||
|
"docs/zh-CN/godot/setting.md",
|
||||||
|
"docs/zh-CN/godot/signal.md"
|
||||||
|
],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/source-generators/index.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": [
|
||||||
|
"ai-libs/CoreGrid/project.godot",
|
||||||
|
"ai-libs/CoreGrid/global",
|
||||||
|
"ai-libs/CoreGrid/scenes"
|
||||||
|
],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"AutoLoad|InputActions|Node|Signal|PackedScene|Godot\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Godot.SourceGenerators": {
|
||||||
|
"aliases": [
|
||||||
|
"godot.sourcegenerators",
|
||||||
|
"godot-source-generators",
|
||||||
|
"godot source generators",
|
||||||
|
"godot generators"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Godot.SourceGenerators"],
|
||||||
|
"project_file": "GFramework.Godot.SourceGenerators/GFramework.Godot.SourceGenerators.csproj",
|
||||||
|
"test_projects": ["GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Godot.SourceGenerators/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/source-generators/godot-project-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/get-node-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/bind-node-signal-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/auto-register-exported-collections-generator.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/godot/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": [
|
||||||
|
"ai-libs/CoreGrid/project.godot",
|
||||||
|
"ai-libs/CoreGrid/global",
|
||||||
|
"ai-libs/CoreGrid/scenes"
|
||||||
|
],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GetNode|BindNodeSignal|AutoRegisterExported|project\\.godot|AutoLoad\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Godot.SourceGenerators.Abstractions": {
|
||||||
|
"aliases": [
|
||||||
|
"godot.sourcegenerators.abstractions",
|
||||||
|
"godot-source-generators-abstractions",
|
||||||
|
"godot source generators abstractions"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Godot.SourceGenerators.Abstractions"],
|
||||||
|
"project_file": "GFramework.Godot.SourceGenerators.Abstractions/GFramework.Godot.SourceGenerators.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.Godot.SourceGenerators.Tests/GFramework.Godot.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": [],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/source-generators/godot-project-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/get-node-generator.md",
|
||||||
|
"docs/zh-CN/source-generators/bind-node-signal-generator.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/godot/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/project.godot", "ai-libs/CoreGrid/global"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Godot\\.SourceGenerators\\.Abstractions|GetNode|BindNodeSignal\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cqrs": {
|
||||||
|
"aliases": ["cqrs", "mediator", "cqrs module"],
|
||||||
|
"source_paths": ["GFramework.Cqrs"],
|
||||||
|
"project_file": "GFramework.Cqrs/GFramework.Cqrs.csproj",
|
||||||
|
"test_projects": ["GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Cqrs/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/core/cqrs.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/core/command.md",
|
||||||
|
"docs/zh-CN/core/query.md",
|
||||||
|
"docs/zh-CN/core/cqrs.md"
|
||||||
|
],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/core/index.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global", "ai-libs/CoreGrid/scripts"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"CommandHandler|QueryHandler|RegisterCqrs|PipelineBehavior\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cqrs.Abstractions": {
|
||||||
|
"aliases": ["cqrs.abstractions", "cqrs-abstractions", "cqrs abstractions"],
|
||||||
|
"source_paths": ["GFramework.Cqrs.Abstractions"],
|
||||||
|
"project_file": "GFramework.Cqrs.Abstractions/GFramework.Cqrs.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Cqrs.Abstractions/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/core/cqrs.md"],
|
||||||
|
"topics": [
|
||||||
|
"docs/zh-CN/core/command.md",
|
||||||
|
"docs/zh-CN/core/query.md"
|
||||||
|
],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Cqrs\\.Abstractions|ICommand|IQuery|IRequest\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cqrs.SourceGenerators": {
|
||||||
|
"aliases": [
|
||||||
|
"cqrs.sourcegenerators",
|
||||||
|
"cqrs-source-generators",
|
||||||
|
"cqrs source generators"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Cqrs.SourceGenerators"],
|
||||||
|
"project_file": "GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj",
|
||||||
|
"test_projects": ["GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Cqrs.SourceGenerators/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/core/cqrs.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/global"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Cqrs\\.SourceGenerators|RequestHandler|PipelineBehavior\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Ecs.Arch": {
|
||||||
|
"aliases": ["ecs.arch", "ecs-arch", "ecs arch", "ecs"],
|
||||||
|
"source_paths": ["GFramework.Ecs.Arch"],
|
||||||
|
"project_file": "GFramework.Ecs.Arch/GFramework.Ecs.Arch.csproj",
|
||||||
|
"test_projects": ["GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj"],
|
||||||
|
"readme_paths": ["GFramework.Ecs.Arch/README.md"],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/ecs/index.md"],
|
||||||
|
"topics": ["docs/zh-CN/ecs/arch.md"],
|
||||||
|
"fallback": [
|
||||||
|
"docs/zh-CN/core/index.md",
|
||||||
|
"docs/zh-CN/api-reference/index.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/scripts", "ai-libs/CoreGrid/global"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"Arch\\.Core|World|SystemGroup|QueryDescription\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Ecs.Arch.Abstractions": {
|
||||||
|
"aliases": [
|
||||||
|
"ecs.arch.abstractions",
|
||||||
|
"ecs-arch-abstractions",
|
||||||
|
"ecs arch abstractions"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.Ecs.Arch.Abstractions"],
|
||||||
|
"project_file": "GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj",
|
||||||
|
"test_projects": ["GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj"],
|
||||||
|
"readme_paths": [],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/ecs/index.md"],
|
||||||
|
"topics": ["docs/zh-CN/ecs/arch.md"],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": ["ai-libs/CoreGrid/scripts"],
|
||||||
|
"search_hints": [
|
||||||
|
"rg -n \"GFramework\\.Ecs\\.Arch\\.Abstractions|IArchSystem|IArchModel\" ai-libs/CoreGrid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SourceGenerators.Common": {
|
||||||
|
"aliases": [
|
||||||
|
"sourcegenerators.common",
|
||||||
|
"source-generators-common",
|
||||||
|
"source generators common"
|
||||||
|
],
|
||||||
|
"source_paths": ["GFramework.SourceGenerators.Common"],
|
||||||
|
"project_file": "GFramework.SourceGenerators.Common/GFramework.SourceGenerators.Common.csproj",
|
||||||
|
"test_projects": ["GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj"],
|
||||||
|
"readme_paths": [],
|
||||||
|
"docs": {
|
||||||
|
"landing": ["docs/zh-CN/source-generators/index.md"],
|
||||||
|
"topics": [],
|
||||||
|
"fallback": ["docs/zh-CN/api-reference/index.md"]
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": [],
|
||||||
|
"search_hints": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docs_section_aliases": {
|
||||||
|
"core": ["Core"],
|
||||||
|
"abstractions": ["Core.Abstractions", "Game.Abstractions", "Ecs.Arch.Abstractions"],
|
||||||
|
"game": ["Game"],
|
||||||
|
"godot": ["Godot"],
|
||||||
|
"cqrs": ["Cqrs"],
|
||||||
|
"ecs": ["Ecs.Arch"],
|
||||||
|
"source-generators": [
|
||||||
|
"Core.SourceGenerators",
|
||||||
|
"Game.SourceGenerators",
|
||||||
|
"Cqrs.SourceGenerators",
|
||||||
|
"Godot.SourceGenerators"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
205
.agents/skills/gframework-doc-refresh/SKILL.md
Normal file
205
.agents/skills/gframework-doc-refresh/SKILL.md
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
---
|
||||||
|
name: gframework-doc-refresh
|
||||||
|
description: Refresh or reassess GFramework documentation for a source module such as Core, Game, Godot, Cqrs, Ecs.Arch, or their generator/abstraction packages. Use this when the user asks to update module docs, re-evaluate landing pages, fix outdated topic pages, refresh API reference coverage, verify adoption paths against source/tests/README, or compare current docs with ai-libs consumer wiring. Recommended command: /gframework-doc-refresh <module>.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Purpose
|
||||||
|
|
||||||
|
Use this skill to refresh GFramework documentation from source-first evidence.
|
||||||
|
|
||||||
|
The public entry is module-driven, not doc-type-driven:
|
||||||
|
|
||||||
|
- Input: a source module or a resolvable docs section alias
|
||||||
|
- Output: the minimal documentation update set needed for that module
|
||||||
|
- Evidence: code, tests, README, current docs, then `ai-libs/`
|
||||||
|
|
||||||
|
Do not start by deciding “this is an API doc task” or “this is a tutorial task”.
|
||||||
|
Decide that only after the module scan.
|
||||||
|
|
||||||
|
# Triggers
|
||||||
|
|
||||||
|
Use this skill when the user asks things like:
|
||||||
|
|
||||||
|
- `refresh docs for Core`
|
||||||
|
- `update Game module docs`
|
||||||
|
- `根据 Godot 模块源码刷新文档`
|
||||||
|
- `重新评估 Cqrs 模块文档并更新`
|
||||||
|
- `核对 Godot.SourceGenerators 的文档状态`
|
||||||
|
- `看看 source-generators 栏目哪些页面已经失真`
|
||||||
|
|
||||||
|
Recommended command form:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/gframework-doc-refresh <module>
|
||||||
|
```
|
||||||
|
|
||||||
|
# Supported Modules
|
||||||
|
|
||||||
|
Canonical module names:
|
||||||
|
|
||||||
|
- `Core`
|
||||||
|
- `Core.Abstractions`
|
||||||
|
- `Core.SourceGenerators`
|
||||||
|
- `Core.SourceGenerators.Abstractions`
|
||||||
|
- `Game`
|
||||||
|
- `Game.Abstractions`
|
||||||
|
- `Game.SourceGenerators`
|
||||||
|
- `Godot`
|
||||||
|
- `Godot.SourceGenerators`
|
||||||
|
- `Godot.SourceGenerators.Abstractions`
|
||||||
|
- `Cqrs`
|
||||||
|
- `Cqrs.Abstractions`
|
||||||
|
- `Cqrs.SourceGenerators`
|
||||||
|
- `Ecs.Arch`
|
||||||
|
- `Ecs.Arch.Abstractions`
|
||||||
|
- `SourceGenerators.Common`
|
||||||
|
|
||||||
|
The canonical mapping lives in `.agents/skills/_shared/module-map.json`.
|
||||||
|
|
||||||
|
If the user supplies a docs section name:
|
||||||
|
|
||||||
|
- resolve it back to a source module first
|
||||||
|
- if it maps to multiple modules, stop at normalization guidance and do not draft docs yet
|
||||||
|
|
||||||
|
# Workflow
|
||||||
|
|
||||||
|
## 1. Normalize the input
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py <module>
|
||||||
|
```
|
||||||
|
|
||||||
|
The script normalizes aliases, reports ambiguity, and prints the module's evidence surface.
|
||||||
|
|
||||||
|
If the result is ambiguous:
|
||||||
|
|
||||||
|
- return the candidate modules
|
||||||
|
- ask the user to pick the intended source module
|
||||||
|
- do not continue into document generation
|
||||||
|
|
||||||
|
## 2. Scan the evidence surface
|
||||||
|
|
||||||
|
For the resolved module, inspect:
|
||||||
|
|
||||||
|
- source directories
|
||||||
|
- `*.csproj`
|
||||||
|
- relevant test projects
|
||||||
|
- sibling `README.md`
|
||||||
|
- mapped `docs/zh-CN` landing pages and topic pages
|
||||||
|
- optional `ai-libs/` consumer evidence when needed
|
||||||
|
|
||||||
|
Always confirm the actual files in the repository.
|
||||||
|
Do not assume the mapping is enough on its own.
|
||||||
|
|
||||||
|
## 3. Decide whether `ai-libs/` is needed
|
||||||
|
|
||||||
|
Use `ai-libs/` when:
|
||||||
|
|
||||||
|
- adoption path is unclear from source and README alone
|
||||||
|
- extension points need a real consumer wiring example
|
||||||
|
- current docs have concepts but lack an end-to-end integration path
|
||||||
|
|
||||||
|
Do not rely on `ai-libs/` for:
|
||||||
|
|
||||||
|
- public API contract definitions
|
||||||
|
- generator diagnostics or semantic guarantees
|
||||||
|
- claims about what the current version officially supports
|
||||||
|
|
||||||
|
If `ai-libs/` conflicts with current source or tests, keep source/tests as the contract and document the migration boundary.
|
||||||
|
|
||||||
|
## 4. Judge the documentation state
|
||||||
|
|
||||||
|
Classify the module into one or more of these states:
|
||||||
|
|
||||||
|
- missing landing page
|
||||||
|
- stale landing page
|
||||||
|
- stale topic page
|
||||||
|
- missing or stale API reference coverage
|
||||||
|
- stale tutorial/example
|
||||||
|
- validation-only
|
||||||
|
|
||||||
|
Base this on evidence, not on the previous docs shape.
|
||||||
|
|
||||||
|
## 5. Choose the output set
|
||||||
|
|
||||||
|
Always prioritize:
|
||||||
|
|
||||||
|
1. README / landing page / adoption path
|
||||||
|
2. topic pages
|
||||||
|
3. API reference
|
||||||
|
4. tutorials
|
||||||
|
|
||||||
|
If the module only needs validation or relinking, do not generate extra pages.
|
||||||
|
|
||||||
|
## 6. Draft or update docs
|
||||||
|
|
||||||
|
Load only the template that matches the output you selected:
|
||||||
|
|
||||||
|
- `templates/module-landing.md`
|
||||||
|
- `templates/topic-refresh.md`
|
||||||
|
- `templates/api-reference.md`
|
||||||
|
- `templates/tutorial.md`
|
||||||
|
|
||||||
|
Keep examples minimal, current, and traceable to source or tests.
|
||||||
|
|
||||||
|
## 7. Validate
|
||||||
|
|
||||||
|
Run the internal validators as needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh <file-or-directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
For site-level confirmation after doc edits:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd docs && bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
# Evidence Order
|
||||||
|
|
||||||
|
Use this exact priority:
|
||||||
|
|
||||||
|
1. source code, XML docs, `*.csproj`
|
||||||
|
2. tests and snapshots
|
||||||
|
3. module `README.md`
|
||||||
|
4. current `docs/zh-CN` pages
|
||||||
|
5. verified `ai-libs/` consumers
|
||||||
|
6. archived docs only as fallback context
|
||||||
|
|
||||||
|
# Output Rules
|
||||||
|
|
||||||
|
- Prefer correcting the adoption path over expanding page count.
|
||||||
|
- Do not copy wording from outdated docs just to keep page volume.
|
||||||
|
- Escape generics outside code blocks.
|
||||||
|
- Keep internal links real and current.
|
||||||
|
- Mark code blocks with explicit languages.
|
||||||
|
- Use the smallest example that demonstrates the current contract.
|
||||||
|
- Consumer examples may align with `ai-libs/`, but must not exceed the current module contract.
|
||||||
|
|
||||||
|
# Validation
|
||||||
|
|
||||||
|
Use the shared standards in `.agents/skills/_shared/DOCUMENTATION_STANDARDS.md`.
|
||||||
|
|
||||||
|
When this skill changes public docs, prefer:
|
||||||
|
|
||||||
|
1. focused validator on touched pages
|
||||||
|
2. `cd docs && bun run build`
|
||||||
|
|
||||||
|
When this skill changes the skill system itself:
|
||||||
|
|
||||||
|
1. validate `SKILL.md` frontmatter exists
|
||||||
|
2. run the module scan script for representative modules
|
||||||
|
3. confirm obsolete `vitepress-*` public entries are gone
|
||||||
|
|
||||||
|
# References
|
||||||
|
|
||||||
|
Read these only when needed:
|
||||||
|
|
||||||
|
- `.agents/skills/_shared/DOCUMENTATION_STANDARDS.md`
|
||||||
|
- `.agents/skills/_shared/module-map.json`
|
||||||
|
- `references/module-selection.md`
|
||||||
|
- `references/evidence-and-ai-libs.md`
|
||||||
|
- `references/output-strategy.md`
|
||||||
4
.agents/skills/gframework-doc-refresh/agents/openai.yaml
Normal file
4
.agents/skills/gframework-doc-refresh/agents/openai.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "GFramework Doc Refresh"
|
||||||
|
short_description: "Refresh module docs from code-first evidence"
|
||||||
|
default_prompt: "Use $gframework-doc-refresh to refresh a GFramework module's docs from source, tests, README, current docs, and ai-libs evidence."
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
# Evidence And `ai-libs`
|
||||||
|
|
||||||
|
The evidence order is fixed:
|
||||||
|
|
||||||
|
1. source code, XML docs, `*.csproj`
|
||||||
|
2. tests and snapshots
|
||||||
|
3. module README
|
||||||
|
4. current `docs/zh-CN`
|
||||||
|
5. `ai-libs/`
|
||||||
|
6. archived docs
|
||||||
|
|
||||||
|
## When To Use `ai-libs`
|
||||||
|
|
||||||
|
Use `ai-libs/` to answer questions like:
|
||||||
|
|
||||||
|
- How is this extension point wired in a real project?
|
||||||
|
- What does the minimal project layout look like?
|
||||||
|
- Which project-side files need to exist for this module to work end to end?
|
||||||
|
|
||||||
|
## When Not To Use `ai-libs`
|
||||||
|
|
||||||
|
Do not use `ai-libs/` as the primary source for:
|
||||||
|
|
||||||
|
- public API semantics
|
||||||
|
- exact generator output guarantees
|
||||||
|
- supported package matrix
|
||||||
|
- diagnostics behavior
|
||||||
|
|
||||||
|
## Conflict Rule
|
||||||
|
|
||||||
|
If `ai-libs/` drifts from the current repo:
|
||||||
|
|
||||||
|
- trust source and tests
|
||||||
|
- mention the drift as a compatibility or migration note
|
||||||
|
- do not document old consumer behavior as if it were still the contract
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
# Module Selection
|
||||||
|
|
||||||
|
Use `.agents/skills/_shared/module-map.json` as the canonical source for:
|
||||||
|
|
||||||
|
- supported modules
|
||||||
|
- aliases
|
||||||
|
- source paths
|
||||||
|
- test projects
|
||||||
|
- README paths
|
||||||
|
- docs landing/topic/fallback pages
|
||||||
|
- `ai-libs/` reference roots
|
||||||
|
|
||||||
|
Selection rules:
|
||||||
|
|
||||||
|
1. Prefer explicit canonical module names.
|
||||||
|
2. Resolve docs section aliases back to source modules before scanning docs.
|
||||||
|
3. If an alias maps to multiple modules, stop and return the candidate list.
|
||||||
|
4. If a module has no dedicated docs section, fall back to the nearest existing landing page or API index instead of inventing a fake section.
|
||||||
|
|
||||||
|
Representative ambiguous inputs:
|
||||||
|
|
||||||
|
- `source-generators` -> likely one of `Core.SourceGenerators`, `Game.SourceGenerators`, `Cqrs.SourceGenerators`, `Godot.SourceGenerators`
|
||||||
|
- `abstractions` -> likely one of `Core.Abstractions`, `Game.Abstractions`, `Ecs.Arch.Abstractions`
|
||||||
|
|
||||||
|
Representative resolvable aliases:
|
||||||
|
|
||||||
|
- `core-abstractions` -> `Core.Abstractions`
|
||||||
|
- `godot generators` -> `Godot.SourceGenerators`
|
||||||
|
- `ecs` -> `Ecs.Arch`
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
# Output Strategy
|
||||||
|
|
||||||
|
The module scan determines the document type.
|
||||||
|
|
||||||
|
Use this priority:
|
||||||
|
|
||||||
|
1. fix README / landing page / adoption path
|
||||||
|
2. fix stale topic pages
|
||||||
|
3. add or refresh API reference coverage
|
||||||
|
4. add or refresh tutorials
|
||||||
|
|
||||||
|
## Landing Page Checklist
|
||||||
|
|
||||||
|
- module purpose
|
||||||
|
- package relationship
|
||||||
|
- minimum adoption path
|
||||||
|
- real entry points
|
||||||
|
- next-reading links
|
||||||
|
|
||||||
|
## Topic Page Checklist
|
||||||
|
|
||||||
|
- current role
|
||||||
|
- public entry points
|
||||||
|
- minimum example
|
||||||
|
- compatibility or migration boundary
|
||||||
|
- related pages
|
||||||
|
|
||||||
|
## API Reference Checklist
|
||||||
|
|
||||||
|
- only for types or members that materially help consumers
|
||||||
|
- grounded in XML docs and source
|
||||||
|
- no speculative examples
|
||||||
|
|
||||||
|
## Tutorial Checklist
|
||||||
|
|
||||||
|
- only after the landing path is accurate
|
||||||
|
- keep the scenario traceable to source/tests or `ai-libs/`
|
||||||
|
- explain why each step exists, not just the code shape
|
||||||
@ -0,0 +1,226 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Normalize a GFramework docs module input and report its evidence surface."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||||
|
REPO_ROOT = SCRIPT_DIR.parents[3]
|
||||||
|
MODULE_MAP_PATH = REPO_ROOT / ".agents/skills/_shared/module-map.json"
|
||||||
|
|
||||||
|
|
||||||
|
def load_module_map() -> dict[str, Any]:
|
||||||
|
return json.loads(MODULE_MAP_PATH.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_key(value: str) -> str:
|
||||||
|
return value.strip().lower().replace("_", "-").replace(" ", "-")
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_module(raw_input: str, module_map: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
modules = module_map["modules"]
|
||||||
|
docs_section_aliases = module_map.get("docs_section_aliases", {})
|
||||||
|
normalized = normalize_key(raw_input)
|
||||||
|
|
||||||
|
for canonical_name in modules:
|
||||||
|
if normalize_key(canonical_name) == normalized:
|
||||||
|
return {"status": "ok", "module": canonical_name, "reason": "canonical"}
|
||||||
|
|
||||||
|
for canonical_name, config in modules.items():
|
||||||
|
aliases = config.get("aliases", [])
|
||||||
|
if normalized in {normalize_key(alias) for alias in aliases}:
|
||||||
|
return {"status": "ok", "module": canonical_name, "reason": "alias"}
|
||||||
|
|
||||||
|
if normalized in docs_section_aliases:
|
||||||
|
candidates = docs_section_aliases[normalized]
|
||||||
|
if len(candidates) == 1:
|
||||||
|
return {"status": "ok", "module": candidates[0], "reason": "docs_section"}
|
||||||
|
return {
|
||||||
|
"status": "ambiguous",
|
||||||
|
"reason": "docs_section",
|
||||||
|
"input": raw_input,
|
||||||
|
"candidates": candidates,
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzzy = [
|
||||||
|
canonical_name
|
||||||
|
for canonical_name in modules
|
||||||
|
if normalized in normalize_key(canonical_name) or normalize_key(canonical_name) in normalized
|
||||||
|
]
|
||||||
|
if fuzzy:
|
||||||
|
return {"status": "unknown", "reason": "closest_match", "input": raw_input, "candidates": fuzzy}
|
||||||
|
|
||||||
|
return {"status": "unknown", "reason": "no_match", "input": raw_input, "candidates": []}
|
||||||
|
|
||||||
|
|
||||||
|
def collect_path_state(paths: list[str]) -> list[dict[str, Any]]:
|
||||||
|
states: list[dict[str, Any]] = []
|
||||||
|
for relative_path in paths:
|
||||||
|
absolute_path = REPO_ROOT / relative_path
|
||||||
|
states.append(
|
||||||
|
{
|
||||||
|
"path": relative_path,
|
||||||
|
"exists": absolute_path.exists(),
|
||||||
|
"kind": "dir" if absolute_path.is_dir() else "file",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return states
|
||||||
|
|
||||||
|
|
||||||
|
def assess_docs(module_config: dict[str, Any]) -> list[str]:
|
||||||
|
docs_config = module_config["docs"]
|
||||||
|
landing = collect_path_state(docs_config.get("landing", []))
|
||||||
|
topics = collect_path_state(docs_config.get("topics", []))
|
||||||
|
assessment: list[str] = []
|
||||||
|
|
||||||
|
if landing and not any(item["exists"] for item in landing):
|
||||||
|
assessment.append("landing_missing")
|
||||||
|
elif landing:
|
||||||
|
assessment.append("landing_present")
|
||||||
|
|
||||||
|
if not topics:
|
||||||
|
assessment.append("topic_docs_not_mapped")
|
||||||
|
else:
|
||||||
|
existing_topics = sum(1 for item in topics if item["exists"])
|
||||||
|
if existing_topics == 0:
|
||||||
|
assessment.append("topic_docs_missing")
|
||||||
|
elif existing_topics < len(topics):
|
||||||
|
assessment.append("topic_docs_partial")
|
||||||
|
else:
|
||||||
|
assessment.append("topic_docs_present")
|
||||||
|
|
||||||
|
return assessment
|
||||||
|
|
||||||
|
|
||||||
|
def build_report(module_name: str, module_config: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
source_paths = collect_path_state(module_config.get("source_paths", []))
|
||||||
|
test_projects = collect_path_state(module_config.get("test_projects", []))
|
||||||
|
readmes = collect_path_state(module_config.get("readme_paths", []))
|
||||||
|
docs_config = module_config["docs"]
|
||||||
|
ai_libs = module_config.get("ai_libs", {})
|
||||||
|
|
||||||
|
report = {
|
||||||
|
"status": "ok",
|
||||||
|
"module": module_name,
|
||||||
|
"source_paths": source_paths,
|
||||||
|
"project_file": collect_path_state([module_config["project_file"]])[0],
|
||||||
|
"test_projects": test_projects,
|
||||||
|
"readme_paths": readmes,
|
||||||
|
"docs": {
|
||||||
|
"landing": collect_path_state(docs_config.get("landing", [])),
|
||||||
|
"topics": collect_path_state(docs_config.get("topics", [])),
|
||||||
|
"fallback": collect_path_state(docs_config.get("fallback", []))
|
||||||
|
},
|
||||||
|
"ai_libs": {
|
||||||
|
"paths": collect_path_state(ai_libs.get("paths", [])),
|
||||||
|
"search_hints": ai_libs.get("search_hints", []),
|
||||||
|
},
|
||||||
|
"assessment": assess_docs(module_config),
|
||||||
|
}
|
||||||
|
|
||||||
|
if readmes and not any(item["exists"] for item in readmes):
|
||||||
|
report["assessment"].append("readme_missing")
|
||||||
|
|
||||||
|
if test_projects and not any(item["exists"] for item in test_projects):
|
||||||
|
report["assessment"].append("tests_missing")
|
||||||
|
|
||||||
|
if not ai_libs.get("paths"):
|
||||||
|
report["assessment"].append("ai_libs_optional")
|
||||||
|
|
||||||
|
if not docs_config.get("topics"):
|
||||||
|
report["assessment"].append("fallback_docs_only")
|
||||||
|
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def print_text_report(report: dict[str, Any]) -> None:
|
||||||
|
if report["status"] != "ok":
|
||||||
|
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"module: {report['module']}")
|
||||||
|
print("assessment:")
|
||||||
|
for item in report["assessment"]:
|
||||||
|
print(f" - {item}")
|
||||||
|
|
||||||
|
print("source:")
|
||||||
|
for item in report["source_paths"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
|
||||||
|
project_file = report["project_file"]
|
||||||
|
print(f"project: {'OK' if project_file['exists'] else 'MISS'} {project_file['path']}")
|
||||||
|
|
||||||
|
print("tests:")
|
||||||
|
for item in report["test_projects"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
|
||||||
|
print("readme:")
|
||||||
|
if report["readme_paths"]:
|
||||||
|
for item in report["readme_paths"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
else:
|
||||||
|
print(" - none mapped")
|
||||||
|
|
||||||
|
print("docs landing:")
|
||||||
|
for item in report["docs"]["landing"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
|
||||||
|
print("docs topics:")
|
||||||
|
if report["docs"]["topics"]:
|
||||||
|
for item in report["docs"]["topics"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
else:
|
||||||
|
print(" - none mapped")
|
||||||
|
|
||||||
|
print("docs fallback:")
|
||||||
|
for item in report["docs"]["fallback"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
|
||||||
|
print("ai-libs:")
|
||||||
|
if report["ai_libs"]["paths"]:
|
||||||
|
for item in report["ai_libs"]["paths"]:
|
||||||
|
print(f" - {'OK' if item['exists'] else 'MISS'} {item['path']}")
|
||||||
|
else:
|
||||||
|
print(" - none mapped")
|
||||||
|
|
||||||
|
if report["ai_libs"]["search_hints"]:
|
||||||
|
print("ai-libs search hints:")
|
||||||
|
for item in report["ai_libs"]["search_hints"]:
|
||||||
|
print(f" - {item}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("module", help="Canonical module name, alias, or docs section name.")
|
||||||
|
parser.add_argument("--json", action="store_true", help="Emit JSON instead of text.")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
module_map = load_module_map()
|
||||||
|
resolution = resolve_module(args.module, module_map)
|
||||||
|
|
||||||
|
if resolution["status"] != "ok":
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(resolution, ensure_ascii=False, indent=2))
|
||||||
|
else:
|
||||||
|
print(json.dumps(resolution, ensure_ascii=False, indent=2))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
report = build_report(resolution["module"], module_map["modules"][resolution["module"]])
|
||||||
|
report["resolution"] = resolution
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||||
|
else:
|
||||||
|
print_text_report(report)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 运行统一文档校验脚本集合。
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TARGET="$1"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
if [ -z "$TARGET" ]; then
|
||||||
|
echo "用法: $0 <文件或目录路径>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "$TARGET" ]; then
|
||||||
|
echo "错误: 路径不存在: $TARGET"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$TARGET" ]; then
|
||||||
|
FILES=("$TARGET")
|
||||||
|
else
|
||||||
|
mapfile -t FILES < <(find "$TARGET" -type f -name "*.md" | sort)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#FILES[@]} -eq 0 ]; then
|
||||||
|
echo "未找到 Markdown 文件"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOTAL_ERRORS=0
|
||||||
|
FAILED_FILES=0
|
||||||
|
|
||||||
|
for FILE in "${FILES[@]}"; do
|
||||||
|
FILE_ERRORS=0
|
||||||
|
|
||||||
|
echo "验证: $FILE"
|
||||||
|
|
||||||
|
if ! bash "$SCRIPT_DIR/validate-frontmatter.sh" "$FILE"; then
|
||||||
|
FILE_ERRORS=$((FILE_ERRORS + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! bash "$SCRIPT_DIR/validate-links.sh" "$FILE"; then
|
||||||
|
FILE_ERRORS=$((FILE_ERRORS + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! bash "$SCRIPT_DIR/validate-code-blocks.sh" "$FILE"; then
|
||||||
|
FILE_ERRORS=$((FILE_ERRORS + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FILE_ERRORS -eq 0 ]; then
|
||||||
|
echo "✓ $FILE"
|
||||||
|
else
|
||||||
|
echo "✗ $FILE"
|
||||||
|
FAILED_FILES=$((FAILED_FILES + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOTAL_ERRORS=$((TOTAL_ERRORS + FILE_ERRORS))
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $TOTAL_ERRORS -eq 0 ]; then
|
||||||
|
echo "✓ 所有验证通过"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✗ 验证失败:$FAILED_FILES 个文件存在问题"
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 验证 Markdown 代码块是否闭合并带有语言标记。
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FILE="$1"
|
||||||
|
|
||||||
|
if [ -z "$FILE" ]; then
|
||||||
|
echo "用法: $0 <文件路径>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$FILE" ]; then
|
||||||
|
echo "错误: 文件不存在: $FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ERROR_COUNT=0
|
||||||
|
WARNING_COUNT=0
|
||||||
|
CODE_FENCE_COUNT=$(grep -c '^```' "$FILE" || true)
|
||||||
|
|
||||||
|
if [ $((CODE_FENCE_COUNT % 2)) -ne 0 ]; then
|
||||||
|
echo "✗ 错误: 存在未闭合的代码块"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
LINE_NUMBER=0
|
||||||
|
while IFS= read -r LINE; do
|
||||||
|
LINE_NUMBER=$((LINE_NUMBER + 1))
|
||||||
|
|
||||||
|
if echo "$LINE" | grep -qE '^```(cs|c#|C#)$'; then
|
||||||
|
echo "⚠ 警告: 第 $LINE_NUMBER 行使用了非标准 C# 标记,建议改为 csharp"
|
||||||
|
WARNING_COUNT=$((WARNING_COUNT + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$LINE" | grep -qE '^```$'; then
|
||||||
|
NEXT_LINE=$(sed -n "$((LINE_NUMBER + 1))p" "$FILE")
|
||||||
|
if [ -n "$NEXT_LINE" ] && ! echo "$NEXT_LINE" | grep -qE '^```'; then
|
||||||
|
echo "⚠ 警告: 第 $LINE_NUMBER 行的代码块缺少语言标记"
|
||||||
|
WARNING_COUNT=$((WARNING_COUNT + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$FILE"
|
||||||
|
|
||||||
|
if [ $ERROR_COUNT -eq 0 ] && [ $WARNING_COUNT -eq 0 ]; then
|
||||||
|
echo "✓ 代码块验证通过"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $ERROR_COUNT -eq 0 ]; then
|
||||||
|
echo "⚠ 代码块验证通过,但有 $WARNING_COUNT 个警告"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✗ 代码块验证失败($ERROR_COUNT 个错误,$WARNING_COUNT 个警告)"
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 验证 Markdown frontmatter。
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FILE="$1"
|
||||||
|
|
||||||
|
if [ -z "$FILE" ]; then
|
||||||
|
echo "用法: $0 <文件路径>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$FILE" ]; then
|
||||||
|
echo "错误: 文件不存在: $FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! head -n 5 "$FILE" | grep -q "^---$"; then
|
||||||
|
echo "✗ 错误: 文件缺少 frontmatter"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/p' "$FILE" | sed '1d;$d')
|
||||||
|
|
||||||
|
if [ -z "$FRONTMATTER" ]; then
|
||||||
|
echo "✗ 错误: frontmatter 为空"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$FRONTMATTER" | grep -q "^title:"; then
|
||||||
|
echo "✗ 错误: 缺少必需字段: title"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$FRONTMATTER" | grep -q "^description:"; then
|
||||||
|
echo "✗ 错误: 缺少必需字段: description"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Frontmatter 验证通过"
|
||||||
@ -1,11 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# 验证内部链接有效性
|
# 验证 Markdown 内部链接是否指向当前仓库中的真实页面。
|
||||||
# 用法: validate-links.sh <文件路径>
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
FILE="$1"
|
FILE="$1"
|
||||||
BASE_DIR="docs/zh-CN"
|
|
||||||
|
|
||||||
if [ -z "$FILE" ]; then
|
if [ -z "$FILE" ]; then
|
||||||
echo "用法: $0 <文件路径>"
|
echo "用法: $0 <文件路径>"
|
||||||
@ -17,58 +15,40 @@ if [ ! -f "$FILE" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "验证内部链接: $FILE"
|
|
||||||
|
|
||||||
# 获取文件所在目录
|
|
||||||
FILE_DIR=$(dirname "$FILE")
|
FILE_DIR=$(dirname "$FILE")
|
||||||
|
|
||||||
# 提取所有 Markdown 链接
|
|
||||||
LINKS=$(grep -oP '\[([^\]]+)\]\(([^)]+)\)' "$FILE" | grep -oP '\(([^)]+)\)' | sed 's/[()]//g' || true)
|
LINKS=$(grep -oP '\[([^\]]+)\]\(([^)]+)\)' "$FILE" | grep -oP '\(([^)]+)\)' | sed 's/[()]//g' || true)
|
||||||
|
|
||||||
if [ -z "$LINKS" ]; then
|
if [ -z "$LINKS" ]; then
|
||||||
echo "✓ 未找到链接"
|
echo "✓ 未找到需要验证的链接"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ERROR_COUNT=0
|
ERROR_COUNT=0
|
||||||
|
|
||||||
while IFS= read -r LINK; do
|
while IFS= read -r LINK; do
|
||||||
# 跳过外部链接
|
if [[ "$LINK" =~ ^https?:// ]] || [[ "$LINK" =~ ^mailto: ]] || [[ "$LINK" =~ ^# ]]; then
|
||||||
if [[ "$LINK" =~ ^https?:// ]]; then
|
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 跳过锚点链接(仅 #开头)
|
|
||||||
if [[ "$LINK" =~ ^# ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 移除锚点部分
|
|
||||||
LINK_PATH=$(echo "$LINK" | sed 's/#.*//')
|
LINK_PATH=$(echo "$LINK" | sed 's/#.*//')
|
||||||
|
|
||||||
# 跳过空路径
|
|
||||||
if [ -z "$LINK_PATH" ]; then
|
if [ -z "$LINK_PATH" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 处理相对路径
|
if [[ "$LINK_PATH" =~ ^/ ]]; then
|
||||||
if [[ "$LINK_PATH" =~ ^\. ]]; then
|
|
||||||
TARGET="$FILE_DIR/$LINK_PATH"
|
|
||||||
# 处理绝对路径
|
|
||||||
elif [[ "$LINK_PATH" =~ ^/ ]]; then
|
|
||||||
TARGET="docs$LINK_PATH"
|
TARGET="docs$LINK_PATH"
|
||||||
# 如果没有扩展名,尝试添加 .md
|
if [[ ! "$TARGET" =~ \.[A-Za-z0-9]+$ ]]; then
|
||||||
if [[ ! "$TARGET" =~ \. ]]; then
|
|
||||||
TARGET="$TARGET.md"
|
TARGET="$TARGET.md"
|
||||||
fi
|
fi
|
||||||
|
elif [[ "$LINK_PATH" =~ ^\. ]]; then
|
||||||
|
TARGET="$FILE_DIR/$LINK_PATH"
|
||||||
else
|
else
|
||||||
TARGET="$FILE_DIR/$LINK_PATH"
|
TARGET="$FILE_DIR/$LINK_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 规范化路径
|
|
||||||
TARGET=$(realpath -m "$TARGET" 2>/dev/null || echo "$TARGET")
|
TARGET=$(realpath -m "$TARGET" 2>/dev/null || echo "$TARGET")
|
||||||
|
|
||||||
# 检查文件是否存在
|
|
||||||
if [ ! -f "$TARGET" ] && [ ! -d "$TARGET" ]; then
|
if [ ! -f "$TARGET" ] && [ ! -d "$TARGET" ]; then
|
||||||
echo "✗ 损坏的链接: $LINK"
|
echo "✗ 损坏的链接: $LINK"
|
||||||
echo " 目标不存在: $TARGET"
|
echo " 目标不存在: $TARGET"
|
||||||
@ -77,9 +57,9 @@ while IFS= read -r LINK; do
|
|||||||
done <<< "$LINKS"
|
done <<< "$LINKS"
|
||||||
|
|
||||||
if [ $ERROR_COUNT -eq 0 ]; then
|
if [ $ERROR_COUNT -eq 0 ]; then
|
||||||
echo "✓ 内部链接验证通过"
|
echo "✓ 链接验证通过"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
|
||||||
echo "✗ 发现 $ERROR_COUNT 个损坏的链接"
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "✗ 共发现 $ERROR_COUNT 个损坏链接"
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: {{API_TITLE}}
|
||||||
|
description: {{API_DESCRIPTION}}
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# {{API_TITLE}}
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
{{API_OVERVIEW}}
|
||||||
|
|
||||||
|
## 适用范围
|
||||||
|
|
||||||
|
{{API_SCOPE}}
|
||||||
|
|
||||||
|
## 关键成员
|
||||||
|
|
||||||
|
{{KEY_MEMBERS}}
|
||||||
|
|
||||||
|
## 最小示例
|
||||||
|
|
||||||
|
{{MINIMUM_EXAMPLE}}
|
||||||
|
|
||||||
|
## 相关类型
|
||||||
|
|
||||||
|
{{RELATED_TYPES}}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: {{MODULE_TITLE}}
|
||||||
|
description: {{MODULE_DESCRIPTION}}
|
||||||
|
---
|
||||||
|
|
||||||
|
# {{MODULE_TITLE}}
|
||||||
|
|
||||||
|
## 模块定位
|
||||||
|
|
||||||
|
{{MODULE_POSITIONING}}
|
||||||
|
|
||||||
|
## 包关系
|
||||||
|
|
||||||
|
{{PACKAGE_RELATIONSHIP}}
|
||||||
|
|
||||||
|
## 最小接入路径
|
||||||
|
|
||||||
|
{{MINIMUM_ADOPTION_PATH}}
|
||||||
|
|
||||||
|
## 关键入口
|
||||||
|
|
||||||
|
{{KEY_ENTRY_POINTS}}
|
||||||
|
|
||||||
|
## 当前边界
|
||||||
|
|
||||||
|
{{CURRENT_BOUNDARIES}}
|
||||||
|
|
||||||
|
## 继续阅读
|
||||||
|
|
||||||
|
{{NEXT_READING}}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
title: {{TOPIC_TITLE}}
|
||||||
|
description: {{TOPIC_DESCRIPTION}}
|
||||||
|
---
|
||||||
|
|
||||||
|
# {{TOPIC_TITLE}}
|
||||||
|
|
||||||
|
## 当前角色
|
||||||
|
|
||||||
|
{{CURRENT_ROLE}}
|
||||||
|
|
||||||
|
## 公开入口
|
||||||
|
|
||||||
|
{{PUBLIC_ENTRY_POINTS}}
|
||||||
|
|
||||||
|
## 最小示例
|
||||||
|
|
||||||
|
{{MINIMUM_EXAMPLE}}
|
||||||
|
|
||||||
|
## 兼容与迁移边界
|
||||||
|
|
||||||
|
{{COMPATIBILITY_BOUNDARY}}
|
||||||
|
|
||||||
|
## 相关页面
|
||||||
|
|
||||||
|
{{RELATED_PAGES}}
|
||||||
30
.agents/skills/gframework-doc-refresh/templates/tutorial.md
Normal file
30
.agents/skills/gframework-doc-refresh/templates/tutorial.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: {{TUTORIAL_TITLE}}
|
||||||
|
description: {{TUTORIAL_DESCRIPTION}}
|
||||||
|
---
|
||||||
|
|
||||||
|
# {{TUTORIAL_TITLE}}
|
||||||
|
|
||||||
|
## 学习目标
|
||||||
|
|
||||||
|
{{LEARNING_OBJECTIVES}}
|
||||||
|
|
||||||
|
## 前置条件
|
||||||
|
|
||||||
|
{{PREREQUISITES}}
|
||||||
|
|
||||||
|
## 步骤
|
||||||
|
|
||||||
|
{{STEP_SEQUENCE}}
|
||||||
|
|
||||||
|
## 完整代码
|
||||||
|
|
||||||
|
{{FULL_CODE}}
|
||||||
|
|
||||||
|
## 验证结果
|
||||||
|
|
||||||
|
{{EXPECTED_RESULT}}
|
||||||
|
|
||||||
|
## 继续阅读
|
||||||
|
|
||||||
|
{{NEXT_READING}}
|
||||||
@ -1,469 +0,0 @@
|
|||||||
# VitePress 文档生成 Skills 系统
|
|
||||||
|
|
||||||
为 GFramework 项目提供自动化的 VitePress 文档生成能力。
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
这是一套专门为 GFramework 项目设计的文档生成 skills,能够根据 C# 源代码自动生成高质量的 VitePress 文档。系统采用模块化设计,每个 skill 专注于特定的文档生成任务。
|
|
||||||
|
|
||||||
## 可用 Skills
|
|
||||||
|
|
||||||
### 1. vitepress-api-doc - API 文档生成
|
|
||||||
|
|
||||||
为单个 C# 文件生成 API 参考文档。
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 类、接口、枚举的 API 文档
|
|
||||||
- 方法、属性、事件的详细说明
|
|
||||||
- 基于 XML 注释生成文档
|
|
||||||
|
|
||||||
**调用方式**:
|
|
||||||
```bash
|
|
||||||
/vitepress-api-doc <C# 文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-api-doc GFramework.Core/architecture/Architecture.cs
|
|
||||||
```
|
|
||||||
|
|
||||||
**输出位置**:`docs/zh-CN/api-reference/<模块>/<文件名>.md`
|
|
||||||
|
|
||||||
[详细文档](./vitepress-api-doc/SKILL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. vitepress-guide - 功能指南生成
|
|
||||||
|
|
||||||
生成功能模块的使用指南文档。
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 核心功能模块的使用说明
|
|
||||||
- 设计模式和架构概念
|
|
||||||
- 最佳实践和常见问题
|
|
||||||
|
|
||||||
**调用方式**:
|
|
||||||
```bash
|
|
||||||
/vitepress-guide <主题> <目标模块>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-guide "事件系统" Core
|
|
||||||
/vitepress-guide "IoC 容器" Core
|
|
||||||
```
|
|
||||||
|
|
||||||
**输出位置**:`docs/zh-CN/<模块>/<主题>.md`
|
|
||||||
|
|
||||||
[详细文档](./vitepress-guide/SKILL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. vitepress-tutorial - 分步教程生成
|
|
||||||
|
|
||||||
生成分步教程文档,适合初学者学习。
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 框架入门教程
|
|
||||||
- 功能实现教程
|
|
||||||
- 问题解决方案
|
|
||||||
|
|
||||||
**调用方式**:
|
|
||||||
```bash
|
|
||||||
/vitepress-tutorial <教程主题>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-tutorial "创建第一个 System"
|
|
||||||
/vitepress-tutorial "使用事件系统"
|
|
||||||
```
|
|
||||||
|
|
||||||
**输出位置**:`docs/zh-CN/tutorials/<主题>.md`
|
|
||||||
|
|
||||||
[详细文档](./vitepress-tutorial/SKILL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. vitepress-batch-api - 批量 API 文档生成
|
|
||||||
|
|
||||||
为整个模块批量生成 API 文档。
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 初始化模块文档
|
|
||||||
- 更新整个模块的文档
|
|
||||||
- 快速生成大量文档
|
|
||||||
|
|
||||||
**调用方式**:
|
|
||||||
```bash
|
|
||||||
/vitepress-batch-api <模块名>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-batch-api Core
|
|
||||||
/vitepress-batch-api Godot
|
|
||||||
```
|
|
||||||
|
|
||||||
**输出位置**:`docs/zh-CN/api-reference/<模块>/`
|
|
||||||
|
|
||||||
[详细文档](./vitepress-batch-api/SKILL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. vitepress-validate - 文档验证
|
|
||||||
|
|
||||||
验证文档的质量和规范性。
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- Frontmatter 格式验证
|
|
||||||
- 内部链接有效性检查
|
|
||||||
- 代码块语法验证
|
|
||||||
- 标点符号规范检查
|
|
||||||
|
|
||||||
**调用方式**:
|
|
||||||
```bash
|
|
||||||
/vitepress-validate <文件或目录路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-validate docs/zh-CN/api-reference/core/architecture.md
|
|
||||||
/vitepress-validate docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
[详细文档](./vitepress-validate/SKILL.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
### 1. 生成单个 API 文档
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 为 Architecture 类生成文档
|
|
||||||
/vitepress-api-doc GFramework.Core/architecture/Architecture.cs
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 批量生成模块文档
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 为整个 Core 模块生成文档
|
|
||||||
/vitepress-batch-api Core
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 生成功能指南
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 生成事件系统使用指南
|
|
||||||
/vitepress-guide "事件系统" Core
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 生成教程
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 生成创建 Model 的教程
|
|
||||||
/vitepress-tutorial "创建第一个 Model"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 验证文档
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 验证生成的文档
|
|
||||||
/vitepress-validate docs/zh-CN/api-reference/core/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
### 典型工作流程
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph TD
|
|
||||||
A[开始] --> B{文档类型?}
|
|
||||||
B -->|API 文档| C[/vitepress-api-doc]
|
|
||||||
B -->|功能指南| D[/vitepress-guide]
|
|
||||||
B -->|教程| E[/vitepress-tutorial]
|
|
||||||
C --> F[/vitepress-validate]
|
|
||||||
D --> F
|
|
||||||
E --> F
|
|
||||||
F --> G{验证通过?}
|
|
||||||
G -->|是| H[完成]
|
|
||||||
G -->|否| I[修复问题]
|
|
||||||
I --> F
|
|
||||||
```
|
|
||||||
|
|
||||||
### 推荐流程
|
|
||||||
|
|
||||||
1. **初始化模块文档**
|
|
||||||
```bash
|
|
||||||
/vitepress-batch-api Core
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **生成功能指南**
|
|
||||||
```bash
|
|
||||||
/vitepress-guide "IoC 容器" Core
|
|
||||||
/vitepress-guide "事件系统" Core
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **生成教程**
|
|
||||||
```bash
|
|
||||||
/vitepress-tutorial "创建第一个 Model"
|
|
||||||
/vitepress-tutorial "使用命令系统"
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **验证所有文档**
|
|
||||||
```bash
|
|
||||||
/vitepress-validate docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
.claude/skills/
|
|
||||||
├── README.md # 本文件
|
|
||||||
├── _shared/ # 共享资源
|
|
||||||
│ └── scripts/ # 共享脚本
|
|
||||||
│ ├── update-vitepress-nav.sh # 更新导航配置
|
|
||||||
│ ├── parse-csharp-xml.sh # 解析 XML 注释
|
|
||||||
│ └── generate-examples.sh # 生成代码示例
|
|
||||||
│
|
|
||||||
├── vitepress-api-doc/ # API 文档生成
|
|
||||||
│ ├── SKILL.md # Skill 说明
|
|
||||||
│ ├── template.md # 文档模板
|
|
||||||
│ └── examples/ # 示例文档
|
|
||||||
│ ├── class-example.md
|
|
||||||
│ ├── interface-example.md
|
|
||||||
│ └── enum-example.md
|
|
||||||
│
|
|
||||||
├── vitepress-guide/ # 功能指南生成
|
|
||||||
│ ├── SKILL.md
|
|
||||||
│ ├── template.md
|
|
||||||
│ └── examples/
|
|
||||||
│ └── guide-example.md
|
|
||||||
│
|
|
||||||
├── vitepress-tutorial/ # 教程生成
|
|
||||||
│ ├── SKILL.md
|
|
||||||
│ ├── template.md
|
|
||||||
│ └── examples/
|
|
||||||
│ └── tutorial-example.md
|
|
||||||
│
|
|
||||||
├── vitepress-batch-api/ # 批量 API 文档生成
|
|
||||||
│ ├── SKILL.md
|
|
||||||
│ └── scripts/
|
|
||||||
│ └── batch-generate.sh
|
|
||||||
│
|
|
||||||
└── vitepress-validate/ # 文档验证
|
|
||||||
├── SKILL.md
|
|
||||||
└── scripts/
|
|
||||||
├── validate-frontmatter.sh
|
|
||||||
├── validate-links.sh
|
|
||||||
├── validate-code-blocks.sh
|
|
||||||
└── validate-all.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 设计原则
|
|
||||||
|
|
||||||
### 1. 单一职责
|
|
||||||
|
|
||||||
每个 skill 专注于一个特定任务:
|
|
||||||
- `vitepress-api-doc` - 单文件 API 文档
|
|
||||||
- `vitepress-guide` - 功能指南
|
|
||||||
- `vitepress-tutorial` - 分步教程
|
|
||||||
- `vitepress-batch-api` - 批量生成
|
|
||||||
- `vitepress-validate` - 质量验证
|
|
||||||
|
|
||||||
### 2. 模块化设计
|
|
||||||
|
|
||||||
- 共享脚本放在 `_shared/scripts/`
|
|
||||||
- 每个 skill 独立维护
|
|
||||||
- 可以单独使用或组合使用
|
|
||||||
|
|
||||||
### 3. 基于源代码
|
|
||||||
|
|
||||||
- 仅使用 XML 注释,不添加 AI 补充
|
|
||||||
- 保持文档与代码同步
|
|
||||||
- 代码示例由 AI 自动生成
|
|
||||||
|
|
||||||
### 4. 质量保证
|
|
||||||
|
|
||||||
- 所有生成的文档都应通过验证
|
|
||||||
- 遵循 VitePress 规范
|
|
||||||
- 保持一致的文档风格
|
|
||||||
|
|
||||||
## 文档规范
|
|
||||||
|
|
||||||
### Frontmatter 格式
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 文档标题
|
|
||||||
description: 简短描述(1-2 句话)
|
|
||||||
outline: deep # 可选
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 代码块标记
|
|
||||||
|
|
||||||
- C# 代码使用 `csharp`
|
|
||||||
- Bash 脚本使用 `bash`
|
|
||||||
- JSON 使用 `json`
|
|
||||||
- YAML 使用 `yaml`
|
|
||||||
|
|
||||||
### 泛型符号转义
|
|
||||||
|
|
||||||
在正文中使用 HTML 实体:
|
|
||||||
- `List<T>` → `List<T>`
|
|
||||||
- 代码块内保持原样
|
|
||||||
|
|
||||||
### 中文标点符号
|
|
||||||
|
|
||||||
- 中文句子使用全角标点:,。!?
|
|
||||||
- 英文句子使用半角标点:,.!?
|
|
||||||
- 代码周围使用半角符号
|
|
||||||
|
|
||||||
## 共享脚本
|
|
||||||
|
|
||||||
### update-vitepress-nav.sh
|
|
||||||
|
|
||||||
更新 VitePress 侧边栏导航配置。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/_shared/scripts/update-vitepress-nav.sh <文件路径> <标题>
|
|
||||||
```
|
|
||||||
|
|
||||||
### parse-csharp-xml.sh
|
|
||||||
|
|
||||||
解析 C# XML 文档注释。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/_shared/scripts/parse-csharp-xml.sh <C# 文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
### generate-examples.sh
|
|
||||||
|
|
||||||
生成代码示例。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/_shared/scripts/generate-examples.sh <类型名> <命名空间>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
### 1. 文档生成顺序
|
|
||||||
|
|
||||||
1. 先生成 API 文档(基础)
|
|
||||||
2. 再生成功能指南(概念)
|
|
||||||
3. 最后生成教程(实践)
|
|
||||||
|
|
||||||
### 2. 保持文档同步
|
|
||||||
|
|
||||||
- 修改代码后及时更新文档
|
|
||||||
- 使用单文件生成更新特定文档
|
|
||||||
- 定期批量验证所有文档
|
|
||||||
|
|
||||||
### 3. 质量控制
|
|
||||||
|
|
||||||
- 生成后立即验证
|
|
||||||
- 修复所有错误和警告
|
|
||||||
- 确保链接有效
|
|
||||||
|
|
||||||
### 4. 版本控制
|
|
||||||
|
|
||||||
- 将生成的文档提交到 Git
|
|
||||||
- 在 PR 中包含文档更新
|
|
||||||
- 保持文档与代码版本一致
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:生成的文档缺少内容
|
|
||||||
|
|
||||||
**原因**:源代码缺少 XML 注释
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
1. 在源代码中添加 XML 注释
|
|
||||||
2. 重新生成文档
|
|
||||||
|
|
||||||
### 问题:验证失败
|
|
||||||
|
|
||||||
**原因**:文档格式不符合规范
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
1. 查看验证错误信息
|
|
||||||
2. 根据提示修复问题
|
|
||||||
3. 重新验证
|
|
||||||
|
|
||||||
### 问题:链接损坏
|
|
||||||
|
|
||||||
**原因**:文件路径错误或文件不存在
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
1. 检查链接的目标文件是否存在
|
|
||||||
2. 修正文件路径
|
|
||||||
3. 重新验证
|
|
||||||
|
|
||||||
### 问题:批量生成速度慢
|
|
||||||
|
|
||||||
**原因**:文件数量多
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
1. 使用 `--parallel` 选项(如果支持)
|
|
||||||
2. 分批生成
|
|
||||||
3. 仅生成修改的文件
|
|
||||||
|
|
||||||
## 扩展开发
|
|
||||||
|
|
||||||
### 添加新 Skill
|
|
||||||
|
|
||||||
1. 在 `.claude/skills/` 下创建新目录
|
|
||||||
2. 创建 `SKILL.md` 说明文档
|
|
||||||
3. 创建必要的模板和脚本
|
|
||||||
4. 在本 README 中添加说明
|
|
||||||
|
|
||||||
### 修改现有 Skill
|
|
||||||
|
|
||||||
1. 更新 `SKILL.md` 文档
|
|
||||||
2. 修改模板或脚本
|
|
||||||
3. 更新示例文档
|
|
||||||
4. 测试修改后的功能
|
|
||||||
|
|
||||||
## 贡献指南
|
|
||||||
|
|
||||||
### 报告问题
|
|
||||||
|
|
||||||
在 GitHub Issues 中报告问题,包含:
|
|
||||||
- 使用的 skill 名称
|
|
||||||
- 输入参数
|
|
||||||
- 预期结果
|
|
||||||
- 实际结果
|
|
||||||
- 错误信息
|
|
||||||
|
|
||||||
### 提交改进
|
|
||||||
|
|
||||||
1. Fork 项目
|
|
||||||
2. 创建功能分支
|
|
||||||
3. 提交修改
|
|
||||||
4. 创建 Pull Request
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 (2025-01-XX) - 初始版本
|
|
||||||
- 5 个核心 skills
|
|
||||||
- 3 个共享脚本
|
|
||||||
- 完整的文档和示例
|
|
||||||
|
|
||||||
## 许可证
|
|
||||||
|
|
||||||
与 GFramework 项目保持一致。
|
|
||||||
|
|
||||||
## 联系方式
|
|
||||||
|
|
||||||
如有问题或建议,请通过以下方式联系:
|
|
||||||
- GitHub Issues
|
|
||||||
- 项目讨论区
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**注意**:本 skills 系统专为 GFramework 项目设计,使用前请确保了解项目结构和文档规范。
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
# GFramework 文档编写规范
|
|
||||||
|
|
||||||
## Markdown 语法规范
|
|
||||||
|
|
||||||
### 1. 泛型标记转义
|
|
||||||
|
|
||||||
在 Markdown 文档中,所有泛型标记必须转义,否则会被 VitePress 误认为 HTML 标签。
|
|
||||||
|
|
||||||
**错误示例**:
|
|
||||||
```markdown
|
|
||||||
`Option<T>` 是一个泛型类型
|
|
||||||
`Result<TValue, TError>` 表示结果
|
|
||||||
public class Repository<TData> { }
|
|
||||||
```
|
|
||||||
|
|
||||||
**正确示例**:
|
|
||||||
```markdown
|
|
||||||
`Option<T>` 是一个泛型类型
|
|
||||||
`Result<TValue, TError>` 表示结果
|
|
||||||
public class Repository<TData> { }
|
|
||||||
```
|
|
||||||
|
|
||||||
**常见泛型标记**:
|
|
||||||
- `<T>` → `<T>`
|
|
||||||
- `<TResult>` → `<TResult>`
|
|
||||||
- `<TValue>` → `<TValue>`
|
|
||||||
- `<TError>` → `<TError>`
|
|
||||||
- `<TSaveData>` → `<TSaveData>`
|
|
||||||
- `<TData>` → `<TData>`
|
|
||||||
- `<TNode>` → `<TNode>`
|
|
||||||
|
|
||||||
### 2. HTML 标签转义
|
|
||||||
|
|
||||||
如果需要在文档中显示 HTML 标签,必须转义:
|
|
||||||
- `<summary>` → `<summary>`
|
|
||||||
- `<param>` → `<param>`
|
|
||||||
- `<returns>` → `<returns>`
|
|
||||||
|
|
||||||
### 3. 链接验证
|
|
||||||
|
|
||||||
**内部链接规则**:
|
|
||||||
- 使用相对路径: `/zh-CN/core/events`
|
|
||||||
- 确保目标文件存在
|
|
||||||
- 不要链接到尚未创建的页面
|
|
||||||
|
|
||||||
**已存在的文档路径**:
|
|
||||||
|
|
||||||
**Core 模块**:
|
|
||||||
- `/zh-CN/core/architecture` - 架构系统
|
|
||||||
- `/zh-CN/core/ioc` - IoC 容器
|
|
||||||
- `/zh-CN/core/events` - 事件系统
|
|
||||||
- `/zh-CN/core/command` - 命令系统
|
|
||||||
- `/zh-CN/core/query` - 查询系统
|
|
||||||
- `/zh-CN/core/model` - Model 系统
|
|
||||||
- `/zh-CN/core/system` - System 系统
|
|
||||||
- `/zh-CN/core/utility` - Utility 系统
|
|
||||||
- `/zh-CN/core/controller` - Controller 系统
|
|
||||||
- `/zh-CN/core/logging` - 日志系统
|
|
||||||
- `/zh-CN/core/pool` - 对象池
|
|
||||||
- `/zh-CN/core/property` - 可绑定属性
|
|
||||||
- `/zh-CN/core/lifecycle` - 生命周期管理
|
|
||||||
- `/zh-CN/core/coroutine` - 协程系统
|
|
||||||
- `/zh-CN/core/resource` - 资源管理
|
|
||||||
- `/zh-CN/core/state-machine` - 状态机
|
|
||||||
- `/zh-CN/core/cqrs` - CQRS 与 Mediator
|
|
||||||
- `/zh-CN/core/functional` - 函数式编程
|
|
||||||
- `/zh-CN/core/pause` - 暂停管理
|
|
||||||
- `/zh-CN/core/configuration` - 配置管理
|
|
||||||
- `/zh-CN/core/ecs` - ECS 系统集成
|
|
||||||
- `/zh-CN/core/extensions` - 扩展方法
|
|
||||||
- `/zh-CN/core/rule` - 规则系统
|
|
||||||
- `/zh-CN/core/environment` - 环境系统
|
|
||||||
- `/zh-CN/core/context` - 上下文系统
|
|
||||||
- `/zh-CN/core/async-initialization` - 异步初始化
|
|
||||||
|
|
||||||
**Game 模块**:
|
|
||||||
- `/zh-CN/game/scene` - 场景系统
|
|
||||||
- `/zh-CN/game/ui` - UI 系统
|
|
||||||
- `/zh-CN/game/data` - 数据与存档
|
|
||||||
- `/zh-CN/game/storage` - 存储系统
|
|
||||||
- `/zh-CN/game/serialization` - 序列化系统
|
|
||||||
- `/zh-CN/game/setting` - 设置系统
|
|
||||||
|
|
||||||
**Godot 模块**:
|
|
||||||
- `/zh-CN/godot/architecture` - Godot 架构集成
|
|
||||||
- `/zh-CN/godot/scene` - Godot 场景系统
|
|
||||||
- `/zh-CN/godot/ui` - Godot UI 系统
|
|
||||||
- `/zh-CN/godot/pool` - Godot 节点池
|
|
||||||
- `/zh-CN/godot/resource` - Godot 资源仓储
|
|
||||||
- `/zh-CN/godot/logging` - Godot 日志系统
|
|
||||||
- `/zh-CN/godot/pause` - Godot 暂停处理
|
|
||||||
- `/zh-CN/godot/extensions` - Godot 扩展
|
|
||||||
- `/zh-CN/godot/coroutine` - Godot 协程
|
|
||||||
- `/zh-CN/godot/signal` - Godot 信号
|
|
||||||
- `/zh-CN/godot/storage` - Godot 存储
|
|
||||||
|
|
||||||
**教程**:
|
|
||||||
- `/zh-CN/tutorials/coroutine-tutorial` - 协程系统教程
|
|
||||||
- `/zh-CN/tutorials/state-machine-tutorial` - 状态机教程
|
|
||||||
- `/zh-CN/tutorials/resource-management` - 资源管理教程
|
|
||||||
- `/zh-CN/tutorials/save-system` - 存档系统教程
|
|
||||||
- `/zh-CN/tutorials/godot-complete-project` - Godot 完整项目
|
|
||||||
- `/zh-CN/tutorials/functional-programming` - 函数式编程实践
|
|
||||||
- `/zh-CN/tutorials/pause-system` - 暂停系统实现
|
|
||||||
- `/zh-CN/tutorials/data-migration` - 数据迁移实践
|
|
||||||
- `/zh-CN/tutorials/godot-integration` - Godot 集成
|
|
||||||
- `/zh-CN/tutorials/advanced-patterns` - 高级模式
|
|
||||||
|
|
||||||
**其他**:
|
|
||||||
- `/zh-CN/getting-started/quick-start` - 快速开始
|
|
||||||
- `/zh-CN/getting-started/installation` - 安装指南
|
|
||||||
- `/zh-CN/best-practices/architecture-patterns` - 架构模式
|
|
||||||
|
|
||||||
**不存在的路径** (不要链接):
|
|
||||||
- `/zh-CN/best-practices/performance` - 尚未创建
|
|
||||||
- `/zh-CN/core/serializer` - 错误路径,应使用 `/zh-CN/game/serialization`
|
|
||||||
|
|
||||||
## 代码块规范
|
|
||||||
|
|
||||||
### 1. 代码块语言标识
|
|
||||||
|
|
||||||
始终指定代码块的语言:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
\`\`\`csharp
|
|
||||||
public class Example { }
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
\`\`\`bash
|
|
||||||
npm install
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 代码注释
|
|
||||||
|
|
||||||
代码示例应包含中文注释:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 创建玩家实体
|
|
||||||
var player = new Player
|
|
||||||
{
|
|
||||||
Name = "玩家1", // 玩家名称
|
|
||||||
Level = 1 // 初始等级
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Frontmatter 规范
|
|
||||||
|
|
||||||
每个文档必须包含正确的 frontmatter:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 文档标题
|
|
||||||
description: 简短描述(1-2 句话)
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
## 文档结构规范
|
|
||||||
|
|
||||||
### 指南文档结构
|
|
||||||
|
|
||||||
1. 概述
|
|
||||||
2. 核心概念
|
|
||||||
3. 基本用法
|
|
||||||
4. 高级用法
|
|
||||||
5. 最佳实践
|
|
||||||
6. 常见问题
|
|
||||||
7. 相关文档
|
|
||||||
|
|
||||||
### 教程文档结构
|
|
||||||
|
|
||||||
1. 学习目标
|
|
||||||
2. 前置条件
|
|
||||||
3. 步骤 1-N (3-7 步)
|
|
||||||
4. 完整代码
|
|
||||||
5. 运行结果
|
|
||||||
6. 下一步
|
|
||||||
7. 相关文档
|
|
||||||
|
|
||||||
## 验证清单
|
|
||||||
|
|
||||||
生成文档后,必须检查:
|
|
||||||
|
|
||||||
- [ ] 所有泛型标记已转义 (`<T>` → `<T>`)
|
|
||||||
- [ ] 所有内部链接指向存在的页面
|
|
||||||
- [ ] Frontmatter 格式正确
|
|
||||||
- [ ] 代码块指定了语言
|
|
||||||
- [ ] 代码包含中文注释
|
|
||||||
- [ ] 文档结构完整
|
|
||||||
- [ ] 没有 HTML 标签错误
|
|
||||||
|
|
||||||
## 自动修复脚本
|
|
||||||
|
|
||||||
如果文档已生成,可以使用以下脚本修复常见问题:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 修复泛型标记
|
|
||||||
sed -i 's/<T>/\<T\>/g' file.md
|
|
||||||
sed -i 's/<TResult>/\<TResult\>/g' file.md
|
|
||||||
sed -i 's/<TValue>/\<TValue\>/g' file.md
|
|
||||||
sed -i 's/<TError>/\<TError\>/g' file.md
|
|
||||||
|
|
||||||
# 验证构建
|
|
||||||
cd docs && bun run build
|
|
||||||
```
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 共享的模块配置
|
|
||||||
# 用于统一管理 GFramework 项目的模块映射关系
|
|
||||||
|
|
||||||
# 根据模块名获取源代码目录
|
|
||||||
get_source_dir() {
|
|
||||||
local MODULE="$1"
|
|
||||||
case "$MODULE" in
|
|
||||||
Core)
|
|
||||||
echo "GFramework.Core"
|
|
||||||
;;
|
|
||||||
Game)
|
|
||||||
echo "GFramework.Game"
|
|
||||||
;;
|
|
||||||
Godot)
|
|
||||||
echo "GFramework.Godot"
|
|
||||||
;;
|
|
||||||
SourceGenerators)
|
|
||||||
echo "GFramework.SourceGenerators"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 根据模块名获取文档输出目录
|
|
||||||
get_docs_dir() {
|
|
||||||
local MODULE="$1"
|
|
||||||
case "$MODULE" in
|
|
||||||
Core)
|
|
||||||
echo "docs/zh-CN/api-reference/core"
|
|
||||||
;;
|
|
||||||
Game)
|
|
||||||
echo "docs/zh-CN/api-reference/game"
|
|
||||||
;;
|
|
||||||
Godot)
|
|
||||||
echo "docs/zh-CN/api-reference/godot"
|
|
||||||
;;
|
|
||||||
SourceGenerators)
|
|
||||||
echo "docs/zh-CN/api-reference/source-generators"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 根据命名空间推断模块名
|
|
||||||
infer_module_from_namespace() {
|
|
||||||
local NAMESPACE="$1"
|
|
||||||
if [[ "$NAMESPACE" == GFramework.Core* ]]; then
|
|
||||||
echo "Core"
|
|
||||||
elif [[ "$NAMESPACE" == GFramework.Game* ]]; then
|
|
||||||
echo "Game"
|
|
||||||
elif [[ "$NAMESPACE" == GFramework.Godot* ]]; then
|
|
||||||
echo "Godot"
|
|
||||||
elif [[ "$NAMESPACE" == GFramework.SourceGenerators* ]]; then
|
|
||||||
echo "SourceGenerators"
|
|
||||||
else
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 获取所有可用模块列表
|
|
||||||
get_all_modules() {
|
|
||||||
echo "Core Game Godot SourceGenerators"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证模块名是否有效
|
|
||||||
is_valid_module() {
|
|
||||||
local MODULE="$1"
|
|
||||||
case "$MODULE" in
|
|
||||||
Core|Game|Godot|SourceGenerators)
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
# VitePress API 文档生成
|
|
||||||
|
|
||||||
为单个 C# 类、接口或枚举生成符合 VitePress 标准的 API 参考文档。
|
|
||||||
|
|
||||||
## 用途
|
|
||||||
|
|
||||||
此 skill 用于从 C# 源代码文件自动生成结构化的 API 文档,包括:
|
|
||||||
- 类型概述和命名空间信息
|
|
||||||
- 构造函数、方法、属性的详细说明
|
|
||||||
- 基于 XML 文档注释的描述
|
|
||||||
- 自动生成的使用示例
|
|
||||||
- 相关类型的交叉引用
|
|
||||||
|
|
||||||
## 调用方式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/vitepress-api-doc <C# 文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-api-doc GFramework.Core/architecture/Architecture.cs
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **读取源代码文件**
|
|
||||||
- 验证文件存在且为 C# 文件
|
|
||||||
- 读取完整的源代码内容
|
|
||||||
|
|
||||||
2. **解析代码结构**
|
|
||||||
- 提取命名空间、类名、访问修饰符
|
|
||||||
- 识别类型(class/interface/enum/struct)
|
|
||||||
- 解析继承关系和实现的接口
|
|
||||||
- 提取所有公共成员(构造函数、方法、属性、事件、字段)
|
|
||||||
|
|
||||||
3. **提取 XML 文档注释**
|
|
||||||
- 解析 `/// <summary>` 标签(类型和成员描述)
|
|
||||||
- 解析 `/// <param>` 标签(参数说明)
|
|
||||||
- 解析 `/// <returns>` 标签(返回值说明)
|
|
||||||
- 解析 `/// <exception>` 标签(异常说明)
|
|
||||||
- 解析 `/// <example>` 标签(示例代码)
|
|
||||||
- 解析 `/// <see cref=""/>` 标签(交叉引用)
|
|
||||||
|
|
||||||
4. **生成 Markdown 文档**
|
|
||||||
- 根据 `template.md` 填充内容
|
|
||||||
- 转义泛型符号(`<T>` → `<T>`)
|
|
||||||
- 生成使用示例(基于 API 签名)
|
|
||||||
- 添加相关文档链接
|
|
||||||
|
|
||||||
5. **确定输出路径**
|
|
||||||
- 根据命名空间确定模块(Core/Game/Godot/SourceGenerators)
|
|
||||||
- 输出到 `docs/zh-CN/api-reference/<模块>/<类名>.md`
|
|
||||||
|
|
||||||
6. **更新 VitePress 配置**
|
|
||||||
- 调用共享脚本 `update-vitepress-nav.sh`
|
|
||||||
- 在侧边栏配置中添加新文档条目
|
|
||||||
|
|
||||||
7. **验证文档质量**
|
|
||||||
- 检查 Frontmatter 格式
|
|
||||||
- 验证内部链接
|
|
||||||
- 确保代码块语法正确
|
|
||||||
|
|
||||||
## 输出规范
|
|
||||||
|
|
||||||
### Frontmatter 格式
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 类名
|
|
||||||
description: 从 XML <summary> 提取的简短描述
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 文档结构
|
|
||||||
|
|
||||||
1. **标题**:使用类名作为一级标题
|
|
||||||
2. **概述**:XML summary 内容
|
|
||||||
3. **命名空间和程序集信息**
|
|
||||||
4. **继承链**(如果适用)
|
|
||||||
5. **构造函数**(如果有)
|
|
||||||
6. **公共方法**(按字母顺序)
|
|
||||||
7. **公共属性**(按字母顺序)
|
|
||||||
8. **公共事件**(如果有)
|
|
||||||
9. **使用示例**(自动生成)
|
|
||||||
10. **另请参阅**(相关类型链接)
|
|
||||||
|
|
||||||
### 代码块格式
|
|
||||||
|
|
||||||
所有 C# 代码块必须使用:
|
|
||||||
```markdown
|
|
||||||
\`\`\`csharp
|
|
||||||
// 代码内容
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
### 泛型符号转义
|
|
||||||
|
|
||||||
- `List<T>` → `List<T>`
|
|
||||||
- `Dictionary<K, V>` → `Dictionary<K, V>`
|
|
||||||
- `IEnumerable<T>` → `IEnumerable<T>`
|
|
||||||
|
|
||||||
### 内部链接格式
|
|
||||||
|
|
||||||
- 相对路径:`[Architecture](./architecture.md)`
|
|
||||||
- 绝对路径:`[Core 架构](/zh-CN/core/architecture)`
|
|
||||||
- 锚点链接:`[构造函数](#构造函数)`
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
1. 项目必须有 VitePress 配置文件(`docs/.vitepress/config.mts`)
|
|
||||||
2. 目标 C# 文件必须存在且可读
|
|
||||||
3. C# 文件必须包含 XML 文档注释(`///`)
|
|
||||||
4. 文件必须包含至少一个公共类型
|
|
||||||
|
|
||||||
## 配置选项
|
|
||||||
|
|
||||||
### 自动检测模块
|
|
||||||
|
|
||||||
根据命名空间自动确定模块:
|
|
||||||
- `GFramework.Core.*` → `core`
|
|
||||||
- `GFramework.Game.*` → `game`
|
|
||||||
- `GFramework.Godot.*` → `godot`
|
|
||||||
- `GFramework.SourceGenerators.*` → `source-generators`
|
|
||||||
|
|
||||||
### 示例生成策略
|
|
||||||
|
|
||||||
- **基本用法**:最简单的 API 调用
|
|
||||||
- **常见场景**:实际应用案例
|
|
||||||
- **高级用法**:复杂配置(如果适用)
|
|
||||||
|
|
||||||
## 示例输出
|
|
||||||
|
|
||||||
参考 `examples/` 目录中的示例文档:
|
|
||||||
- `class-example.md` - 类文档示例
|
|
||||||
- `interface-example.md` - 接口文档示例
|
|
||||||
- `enum-example.md` - 枚举文档示例
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **仅使用 XML 注释**:不对缺失的注释进行 AI 补充
|
|
||||||
2. **仅提取公共成员**:忽略 `internal`、`private`、`protected` 成员
|
|
||||||
3. **保持文档同步**:文档内容直接来源于代码,确保准确性
|
|
||||||
4. **遵循项目风格**:参考现有文档的格式和术语
|
|
||||||
|
|
||||||
## 相关 Skills
|
|
||||||
|
|
||||||
- `/vitepress-validate` - 验证生成的文档质量
|
|
||||||
- `/vitepress-batch-api` - 批量生成整个模块的 API 文档
|
|
||||||
|
|
||||||
## 技术细节
|
|
||||||
|
|
||||||
### XML 注释标签映射
|
|
||||||
|
|
||||||
| XML 标签 | Markdown 输出 |
|
|
||||||
|---------|--------------|
|
|
||||||
| `<summary>` | 概述章节 |
|
|
||||||
| `<param name="x">` | 参数列表 |
|
|
||||||
| `<returns>` | 返回值说明 |
|
|
||||||
| `<exception cref="T">` | 异常列表 |
|
|
||||||
| `<example>` | 示例代码块 |
|
|
||||||
| `<see cref="T"/>` | 内部链接 |
|
|
||||||
| `<remarks>` | 备注章节 |
|
|
||||||
|
|
||||||
### 成员签名格式
|
|
||||||
|
|
||||||
**方法**:
|
|
||||||
```markdown
|
|
||||||
### MethodName
|
|
||||||
|
|
||||||
描述内容
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
\`\`\`csharp
|
|
||||||
public ReturnType MethodName(ParamType param)
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `param` (ParamType): 参数说明
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (ReturnType): 返回值说明
|
|
||||||
```
|
|
||||||
|
|
||||||
**属性**:
|
|
||||||
```markdown
|
|
||||||
### PropertyName
|
|
||||||
|
|
||||||
描述内容
|
|
||||||
|
|
||||||
**类型**:`PropertyType`
|
|
||||||
|
|
||||||
**访问**:get / set
|
|
||||||
```
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:找不到 XML 注释
|
|
||||||
**解决方案**:确保 C# 文件包含 `///` 注释,而不是 `//` 或 `/* */`
|
|
||||||
|
|
||||||
### 问题:泛型符号显示错误
|
|
||||||
**解决方案**:VitePress 配置中已包含 `safeGenericEscapePlugin`,确保正确转义
|
|
||||||
|
|
||||||
### 问题:侧边栏未更新
|
|
||||||
**解决方案**:检查 `update-vitepress-nav.sh` 脚本是否正确执行
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 - 初始版本,支持类、接口、枚举的文档生成
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
---
|
|
||||||
title: Architecture
|
|
||||||
description: 架构基类,提供系统、模型、工具等组件的注册与管理功能。专注于生命周期管理、初始化流程控制和架构阶段转换。
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
|
|
||||||
# Architecture
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
架构基类,提供系统、模型、工具等组件的注册与管理功能。专注于生命周期管理、初始化流程控制和架构阶段转换。
|
|
||||||
|
|
||||||
**命名空间**:`GFramework.Core.architecture`
|
|
||||||
**程序集**:`GFramework.Core`
|
|
||||||
**继承**:`Object` → `Architecture`
|
|
||||||
**实现**:`IArchitecture`
|
|
||||||
|
|
||||||
## 构造函数
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
创建架构实例。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public Architecture(
|
|
||||||
IArchitectureConfiguration? configuration = null,
|
|
||||||
IEnvironment? environment = null,
|
|
||||||
IArchitectureServices? services = null,
|
|
||||||
IArchitectureContext? context = null
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `configuration` (IArchitectureConfiguration?): 架构配置对象,为 null 时使用默认配置
|
|
||||||
- `environment` (IEnvironment?): 环境配置对象,为 null 时使用默认环境
|
|
||||||
- `services` (IArchitectureServices?): 架构服务对象,为 null 时创建新实例
|
|
||||||
- `context` (IArchitectureContext?): 架构上下文对象,为 null 时创建新实例
|
|
||||||
|
|
||||||
## 公共方法
|
|
||||||
|
|
||||||
### Initialize
|
|
||||||
|
|
||||||
同步初始化架构,阻塞当前线程直到初始化完成。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public void Initialize()
|
|
||||||
```
|
|
||||||
|
|
||||||
**特点**:
|
|
||||||
- 阻塞式初始化
|
|
||||||
- 适用于简单场景或控制台应用
|
|
||||||
- 初始化失败时抛出异常并进入 `FailedInitialization` 阶段
|
|
||||||
|
|
||||||
### InitializeAsync
|
|
||||||
|
|
||||||
异步初始化架构,返回 Task 以便调用者可以等待初始化完成。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public async Task InitializeAsync()
|
|
||||||
```
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (Task): 表示异步初始化操作的任务
|
|
||||||
|
|
||||||
**特点**:
|
|
||||||
- 非阻塞式初始化
|
|
||||||
- 支持异步组件初始化
|
|
||||||
- 适用于需要异步加载资源的场景
|
|
||||||
|
|
||||||
### InstallModule
|
|
||||||
|
|
||||||
安装架构模块,用于扩展架构功能。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public IArchitectureModule InstallModule(IArchitectureModule module)
|
|
||||||
```
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `module` (IArchitectureModule): 要安装的模块实例
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (IArchitectureModule): 返回安装的模块实例
|
|
||||||
|
|
||||||
### RegisterSystem
|
|
||||||
|
|
||||||
注册系统组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public void RegisterSystem<TSystem>(TSystem system) where TSystem : ISystem
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TSystem`: 系统类型,必须实现 ISystem 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `system` (TSystem): 要注册的系统实例
|
|
||||||
|
|
||||||
### RegisterModel
|
|
||||||
|
|
||||||
注册模型组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public void RegisterModel<TModel>(TModel model) where TModel : IModel
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TModel`: 模型类型,必须实现 IModel 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `model` (TModel): 要注册的模型实例
|
|
||||||
|
|
||||||
### RegisterUtility
|
|
||||||
|
|
||||||
注册工具组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public void RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TUtility`: 工具类型,必须实现 IUtility 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `utility` (TUtility): 要注册的工具实例
|
|
||||||
|
|
||||||
### SendCommand
|
|
||||||
|
|
||||||
发送并执行命令。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public void SendCommand(ICommand command)
|
|
||||||
```
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `command` (ICommand): 要执行的命令实例
|
|
||||||
|
|
||||||
### SendCommand<TResult>
|
|
||||||
|
|
||||||
发送并执行带返回值的命令。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
public TResult SendCommand<TResult>(ICommand<TResult> command)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TResult`: 命令返回值类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `command` (ICommand<TResult>): 要执行的命令实例
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (TResult): 命令执行结果
|
|
||||||
|
|
||||||
## 公共属性
|
|
||||||
|
|
||||||
### CurrentPhase
|
|
||||||
|
|
||||||
获取当前架构的阶段。
|
|
||||||
|
|
||||||
**类型**:`ArchitecturePhase`
|
|
||||||
**访问**:get
|
|
||||||
|
|
||||||
### Context
|
|
||||||
|
|
||||||
获取架构上下文,提供对架构服务的访问。
|
|
||||||
|
|
||||||
**类型**:`IArchitectureContext`
|
|
||||||
**访问**:get
|
|
||||||
|
|
||||||
### IsReady
|
|
||||||
|
|
||||||
获取一个布尔值,指示当前架构是否处于就绪状态。
|
|
||||||
|
|
||||||
**类型**:`bool`
|
|
||||||
**访问**:get
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基本用法
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 1. 定义你的架构(继承 Architecture 基类)
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
// 注册 Model
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
RegisterModel(new InventoryModel());
|
|
||||||
|
|
||||||
// 注册 System
|
|
||||||
RegisterSystem(new GameplaySystem());
|
|
||||||
RegisterSystem(new SaveSystem());
|
|
||||||
|
|
||||||
// 注册 Utility
|
|
||||||
RegisterUtility(new StorageUtility());
|
|
||||||
RegisterUtility(new TimeUtility());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 创建并初始化架构
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
architecture.Initialize();
|
|
||||||
|
|
||||||
// 3. 等待架构就绪
|
|
||||||
await architecture.WaitUntilReadyAsync();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 异步初始化
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
await architecture.InitializeAsync(); // 异步等待初始化完成
|
|
||||||
|
|
||||||
// 检查架构是否已就绪
|
|
||||||
if (architecture.IsReady)
|
|
||||||
{
|
|
||||||
Console.WriteLine("架构已就绪,可以开始游戏");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用自定义配置
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var config = new ArchitectureConfiguration
|
|
||||||
{
|
|
||||||
ArchitectureProperties = new ArchitectureProperties
|
|
||||||
{
|
|
||||||
StrictPhaseValidation = true, // 启用严格阶段验证
|
|
||||||
AllowLateRegistration = false // 禁止就绪后注册组件
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var architecture = new GameArchitecture(configuration: config);
|
|
||||||
architecture.Initialize();
|
|
||||||
```
|
|
||||||
|
|
||||||
## 另请参阅
|
|
||||||
|
|
||||||
- [IArchitecture](./iarchitecture.md) - 架构接口
|
|
||||||
- [ArchitecturePhase](./architecture-phase.md) - 架构阶段枚举
|
|
||||||
- [IArchitectureModule](./iarchitecture-module.md) - 架构模块接口
|
|
||||||
- [架构组件](/zh-CN/core/architecture) - 架构使用指南
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
---
|
|
||||||
title: ArchitecturePhase
|
|
||||||
description: 架构阶段枚举,定义了架构生命周期的各个阶段。
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
|
|
||||||
# ArchitecturePhase
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
架构阶段枚举,定义了架构生命周期的各个阶段。
|
|
||||||
|
|
||||||
**命名空间**:`GFramework.Core.Abstractions.enums`
|
|
||||||
**程序集**:`GFramework.Core.Abstractions`
|
|
||||||
**基础类型**:`Enum`
|
|
||||||
|
|
||||||
## 枚举值
|
|
||||||
|
|
||||||
### None
|
|
||||||
|
|
||||||
初始阶段,架构尚未开始初始化。
|
|
||||||
|
|
||||||
**值**:`0`
|
|
||||||
|
|
||||||
### BeforeUtilityInit
|
|
||||||
|
|
||||||
工具初始化前阶段。
|
|
||||||
|
|
||||||
**值**:`1`
|
|
||||||
|
|
||||||
### AfterUtilityInit
|
|
||||||
|
|
||||||
工具初始化后阶段。
|
|
||||||
|
|
||||||
**值**:`2`
|
|
||||||
|
|
||||||
### BeforeModelInit
|
|
||||||
|
|
||||||
模型初始化前阶段。
|
|
||||||
|
|
||||||
**值**:`3`
|
|
||||||
|
|
||||||
### AfterModelInit
|
|
||||||
|
|
||||||
模型初始化后阶段。
|
|
||||||
|
|
||||||
**值**:`4`
|
|
||||||
|
|
||||||
### BeforeSystemInit
|
|
||||||
|
|
||||||
系统初始化前阶段。
|
|
||||||
|
|
||||||
**值**:`5`
|
|
||||||
|
|
||||||
### AfterSystemInit
|
|
||||||
|
|
||||||
系统初始化后阶段。
|
|
||||||
|
|
||||||
**值**:`6`
|
|
||||||
|
|
||||||
### Ready
|
|
||||||
|
|
||||||
就绪状态,架构已完全初始化并可以使用。
|
|
||||||
|
|
||||||
**值**:`7`
|
|
||||||
|
|
||||||
### FailedInitialization
|
|
||||||
|
|
||||||
初始化失败状态。
|
|
||||||
|
|
||||||
**值**:`8`
|
|
||||||
|
|
||||||
### Destroying
|
|
||||||
|
|
||||||
正在销毁阶段。
|
|
||||||
|
|
||||||
**值**:`9`
|
|
||||||
|
|
||||||
### Destroyed
|
|
||||||
|
|
||||||
已销毁阶段。
|
|
||||||
|
|
||||||
**值**:`10`
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 检查架构阶段
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
architecture.Initialize();
|
|
||||||
|
|
||||||
// 检查架构是否已就绪
|
|
||||||
if (architecture.CurrentPhase == ArchitecturePhase.Ready)
|
|
||||||
{
|
|
||||||
Console.WriteLine("架构已就绪,可以开始游戏");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 监听阶段变化
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class PhaseMonitor : IArchitectureLifecycle
|
|
||||||
{
|
|
||||||
public void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
|
|
||||||
{
|
|
||||||
switch (phase)
|
|
||||||
{
|
|
||||||
case ArchitecturePhase.BeforeUtilityInit:
|
|
||||||
Console.WriteLine("开始初始化工具");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.AfterUtilityInit:
|
|
||||||
Console.WriteLine("工具初始化完成");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.BeforeModelInit:
|
|
||||||
Console.WriteLine("开始初始化模型");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.AfterModelInit:
|
|
||||||
Console.WriteLine("模型初始化完成");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.BeforeSystemInit:
|
|
||||||
Console.WriteLine("开始初始化系统");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.AfterSystemInit:
|
|
||||||
Console.WriteLine("系统初始化完成");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.Ready:
|
|
||||||
Console.WriteLine("架构就绪");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.FailedInitialization:
|
|
||||||
Console.WriteLine("架构初始化失败");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.Destroying:
|
|
||||||
Console.WriteLine("架构正在销毁");
|
|
||||||
break;
|
|
||||||
case ArchitecturePhase.Destroyed:
|
|
||||||
Console.WriteLine("架构已销毁");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册监听器
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
architecture.RegisterLifecycleHook(new PhaseMonitor());
|
|
||||||
architecture.Initialize();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 等待特定阶段
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public async Task WaitForReady(IArchitecture architecture)
|
|
||||||
{
|
|
||||||
while (architecture.CurrentPhase != ArchitecturePhase.Ready)
|
|
||||||
{
|
|
||||||
if (architecture.CurrentPhase == ArchitecturePhase.FailedInitialization)
|
|
||||||
{
|
|
||||||
throw new Exception("架构初始化失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("架构已就绪");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 阶段转换顺序
|
|
||||||
|
|
||||||
正常初始化流程的阶段转换顺序:
|
|
||||||
|
|
||||||
1. `None` → `BeforeUtilityInit`
|
|
||||||
2. `BeforeUtilityInit` → `AfterUtilityInit`
|
|
||||||
3. `AfterUtilityInit` → `BeforeModelInit`
|
|
||||||
4. `BeforeModelInit` → `AfterModelInit`
|
|
||||||
5. `AfterModelInit` → `BeforeSystemInit`
|
|
||||||
6. `BeforeSystemInit` → `AfterSystemInit`
|
|
||||||
7. `AfterSystemInit` → `Ready`
|
|
||||||
|
|
||||||
销毁流程的阶段转换顺序:
|
|
||||||
|
|
||||||
1. `Ready` → `Destroying`
|
|
||||||
2. `Destroying` → `Destroyed`
|
|
||||||
|
|
||||||
异常流程:
|
|
||||||
|
|
||||||
- 任何阶段 → `FailedInitialization`(初始化过程中发生异常)
|
|
||||||
|
|
||||||
## 另请参阅
|
|
||||||
|
|
||||||
- [Architecture](./architecture.md) - 架构基类
|
|
||||||
- [IArchitectureLifecycle](./iarchitecture-lifecycle.md) - 生命周期钩子接口
|
|
||||||
- [架构组件](/zh-CN/core/architecture) - 架构使用指南
|
|
||||||
@ -1,290 +0,0 @@
|
|||||||
---
|
|
||||||
title: IArchitecture
|
|
||||||
description: 架构接口,定义了框架的核心功能契约。
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
|
|
||||||
# IArchitecture
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
架构接口,定义了框架的核心功能契约。
|
|
||||||
|
|
||||||
**命名空间**:`GFramework.Core.Abstractions.architecture`
|
|
||||||
**程序集**:`GFramework.Core.Abstractions`
|
|
||||||
**实现类**:[Architecture](./architecture.md)
|
|
||||||
|
|
||||||
## 公共方法
|
|
||||||
|
|
||||||
### RegisterSystem<TSystem>
|
|
||||||
|
|
||||||
注册系统组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void RegisterSystem<TSystem>(TSystem system) where TSystem : ISystem
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TSystem`: 系统类型,必须实现 ISystem 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `system` (TSystem): 要注册的系统实例
|
|
||||||
|
|
||||||
### RegisterModel<TModel>
|
|
||||||
|
|
||||||
注册模型组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void RegisterModel<TModel>(TModel model) where TModel : IModel
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TModel`: 模型类型,必须实现 IModel 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `model` (TModel): 要注册的模型实例
|
|
||||||
|
|
||||||
### RegisterUtility<TUtility>
|
|
||||||
|
|
||||||
注册工具组件到架构中。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TUtility`: 工具类型,必须实现 IUtility 接口
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `utility` (TUtility): 要注册的工具实例
|
|
||||||
|
|
||||||
### GetModel<T>
|
|
||||||
|
|
||||||
从容器中获取已注册的模型。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
T GetModel<T>() where T : class, IModel
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 模型类型
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (T): 模型实例
|
|
||||||
|
|
||||||
### GetSystem<T>
|
|
||||||
|
|
||||||
从容器中获取已注册的系统。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
T GetSystem<T>() where T : class, ISystem
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 系统类型
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (T): 系统实例
|
|
||||||
|
|
||||||
### GetUtility<T>
|
|
||||||
|
|
||||||
从容器中获取已注册的工具。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
T GetUtility<T>() where T : class, IUtility
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 工具类型
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (T): 工具实例
|
|
||||||
|
|
||||||
### SendCommand
|
|
||||||
|
|
||||||
发送并执行命令。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void SendCommand(ICommand command)
|
|
||||||
```
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `command` (ICommand): 要执行的命令实例
|
|
||||||
|
|
||||||
### SendCommand<TResult>
|
|
||||||
|
|
||||||
发送并执行带返回值的命令。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
TResult SendCommand<TResult>(ICommand<TResult> command)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TResult`: 命令返回值类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `command` (ICommand<TResult>): 要执行的命令实例
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (TResult): 命令执行结果
|
|
||||||
|
|
||||||
### SendQuery<TResult>
|
|
||||||
|
|
||||||
发送并执行查询。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
TResult SendQuery<TResult>(IQuery<TResult> query)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `TResult`: 查询返回值类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `query` (IQuery<TResult>): 要执行的查询实例
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (TResult): 查询结果
|
|
||||||
|
|
||||||
### SendEvent<T>
|
|
||||||
|
|
||||||
发送事件(无参数)。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void SendEvent<T>() where T : new()
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 事件类型,必须有无参构造函数
|
|
||||||
|
|
||||||
### SendEvent<T>
|
|
||||||
|
|
||||||
发送事件(带参数)。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void SendEvent<T>(T e)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 事件类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `e` (T): 事件实例
|
|
||||||
|
|
||||||
### RegisterEvent<T>
|
|
||||||
|
|
||||||
注册事件监听器。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
IUnRegister RegisterEvent<T>(Action<T> onEvent)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 事件类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `onEvent` (Action<T>): 事件处理回调
|
|
||||||
|
|
||||||
**返回值**:
|
|
||||||
- (IUnRegister): 用于注销事件的对象
|
|
||||||
|
|
||||||
### UnRegisterEvent<T>
|
|
||||||
|
|
||||||
注销事件监听器。
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
```csharp
|
|
||||||
void UnRegisterEvent<T>(Action<T> onEvent)
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型参数**:
|
|
||||||
- `T`: 事件类型
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `onEvent` (Action<T>): 要注销的事件处理回调
|
|
||||||
|
|
||||||
## 公共属性
|
|
||||||
|
|
||||||
### CurrentPhase
|
|
||||||
|
|
||||||
获取当前架构的阶段。
|
|
||||||
|
|
||||||
**类型**:`ArchitecturePhase`
|
|
||||||
**访问**:get
|
|
||||||
|
|
||||||
### Context
|
|
||||||
|
|
||||||
获取架构上下文。
|
|
||||||
|
|
||||||
**类型**:`IArchitectureContext`
|
|
||||||
**访问**:get
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 在 Controller 中使用
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class GameController : IController
|
|
||||||
{
|
|
||||||
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
// 获取 Model
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
|
|
||||||
// 发送命令
|
|
||||||
this.SendCommand(new StartGameCommand());
|
|
||||||
|
|
||||||
// 发送查询
|
|
||||||
var score = this.SendQuery(new GetScoreQuery());
|
|
||||||
|
|
||||||
// 注册事件
|
|
||||||
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPlayerDied(PlayerDiedEvent e)
|
|
||||||
{
|
|
||||||
// 处理玩家死亡事件
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 实现自定义架构
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
// 单例访问
|
|
||||||
public static IArchitecture Interface { get; private set; }
|
|
||||||
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
Interface = this;
|
|
||||||
|
|
||||||
// 注册组件
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
RegisterSystem(new GameplaySystem());
|
|
||||||
RegisterUtility(new StorageUtility());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 另请参阅
|
|
||||||
|
|
||||||
- [Architecture](./architecture.md) - 架构基类实现
|
|
||||||
- [IModel](./imodel.md) - 模型接口
|
|
||||||
- [ISystem](./isystem.md) - 系统接口
|
|
||||||
- [IUtility](./iutility.md) - 工具接口
|
|
||||||
- [架构组件](/zh-CN/core/architecture) - 架构使用指南
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
title: {{CLASS_NAME}}
|
|
||||||
description: {{XML_SUMMARY}}
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
|
|
||||||
# {{CLASS_NAME}}
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
{{XML_SUMMARY}}
|
|
||||||
|
|
||||||
**命名空间**:`{{NAMESPACE}}`
|
|
||||||
**程序集**:`{{ASSEMBLY}}`
|
|
||||||
{{INHERITANCE_CHAIN}}
|
|
||||||
|
|
||||||
## 构造函数
|
|
||||||
|
|
||||||
{{CONSTRUCTORS}}
|
|
||||||
|
|
||||||
## 公共方法
|
|
||||||
|
|
||||||
{{PUBLIC_METHODS}}
|
|
||||||
|
|
||||||
## 公共属性
|
|
||||||
|
|
||||||
{{PUBLIC_PROPERTIES}}
|
|
||||||
|
|
||||||
{{PUBLIC_EVENTS}}
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
{{AUTO_GENERATED_EXAMPLES}}
|
|
||||||
|
|
||||||
## 另请参阅
|
|
||||||
|
|
||||||
{{RELATED_TYPES}}
|
|
||||||
@ -1,364 +0,0 @@
|
|||||||
# VitePress 批量 API 文档生成
|
|
||||||
|
|
||||||
为整个模块批量生成 API 参考文档,提高文档生成效率。
|
|
||||||
|
|
||||||
## 用途
|
|
||||||
|
|
||||||
此 skill 用于批量生成模块的 API 文档,适用于:
|
|
||||||
- 初始化模块文档
|
|
||||||
- 更新整个模块的文档
|
|
||||||
- 为新模块快速生成文档
|
|
||||||
- 重新生成所有 API 文档
|
|
||||||
|
|
||||||
## 调用方式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/vitepress-batch-api <模块名>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-batch-api Core
|
|
||||||
/vitepress-batch-api Game
|
|
||||||
/vitepress-batch-api Godot
|
|
||||||
/vitepress-batch-api SourceGenerators
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **扫描模块目录**
|
|
||||||
- 根据模块名确定源代码目录
|
|
||||||
- 递归扫描所有 C# 文件
|
|
||||||
|
|
||||||
2. **过滤目标文件**
|
|
||||||
- 仅包含公共类型(public class/interface/enum/struct)
|
|
||||||
- 排除内部类型(internal)
|
|
||||||
- 排除生成的代码(*.g.cs、*.Designer.cs)
|
|
||||||
- 排除测试文件(*.Tests.cs)
|
|
||||||
|
|
||||||
3. **批量生成文档**
|
|
||||||
- 为每个类型调用 `/vitepress-api-doc`
|
|
||||||
- 显示进度信息
|
|
||||||
- 收集生成结果
|
|
||||||
|
|
||||||
4. **生成模块索引页**
|
|
||||||
- 创建 `index.md` 列出所有 API
|
|
||||||
- 按类别分组(类、接口、枚举)
|
|
||||||
- 添加简短描述
|
|
||||||
|
|
||||||
5. **批量更新导航**
|
|
||||||
- 在 VitePress 配置中添加所有新文档
|
|
||||||
- 保持字母顺序
|
|
||||||
- 更新模块索引
|
|
||||||
|
|
||||||
6. **生成摘要报告**
|
|
||||||
- 统计生成的文档数量
|
|
||||||
- 列出成功和失败的文件
|
|
||||||
- 提供验证建议
|
|
||||||
|
|
||||||
## 输出规范
|
|
||||||
|
|
||||||
### 模块索引页格式
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
---
|
|
||||||
title: Core API 参考
|
|
||||||
description: GFramework.Core 模块的 API 参考文档
|
|
||||||
---
|
|
||||||
|
|
||||||
# Core API 参考
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
GFramework.Core 是框架的核心模块,提供架构基础、依赖注入、事件系统等核心功能。
|
|
||||||
|
|
||||||
## 类
|
|
||||||
|
|
||||||
- [Architecture](./architecture.md) - 架构基类
|
|
||||||
- [ArchitectureConfiguration](./architecture-configuration.md) - 架构配置
|
|
||||||
- [IocContainer](./ioc-container.md) - IoC 容器
|
|
||||||
|
|
||||||
## 接口
|
|
||||||
|
|
||||||
- [IArchitecture](./iarchitecture.md) - 架构接口
|
|
||||||
- [IModel](./imodel.md) - 模型接口
|
|
||||||
- [ISystem](./isystem.md) - 系统接口
|
|
||||||
|
|
||||||
## 枚举
|
|
||||||
|
|
||||||
- [ArchitecturePhase](./architecture-phase.md) - 架构阶段
|
|
||||||
```
|
|
||||||
|
|
||||||
### 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
docs/zh-CN/api-reference/
|
|
||||||
├── core/
|
|
||||||
│ ├── index.md # 模块索引
|
|
||||||
│ ├── architecture.md
|
|
||||||
│ ├── iarchitecture.md
|
|
||||||
│ └── ...
|
|
||||||
├── game/
|
|
||||||
│ ├── index.md
|
|
||||||
│ └── ...
|
|
||||||
└── godot/
|
|
||||||
├── index.md
|
|
||||||
└── ...
|
|
||||||
```
|
|
||||||
|
|
||||||
## 模块映射
|
|
||||||
|
|
||||||
### 源代码目录映射
|
|
||||||
|
|
||||||
| 模块名 | 源代码目录 | 输出目录 |
|
|
||||||
|--------|-----------|---------|
|
|
||||||
| Core | `GFramework.Core/` | `docs/zh-CN/api-reference/core/` |
|
|
||||||
| Game | `GFramework.Game/` | `docs/zh-CN/api-reference/game/` |
|
|
||||||
| Godot | `GFramework.Godot/` | `docs/zh-CN/api-reference/godot/` |
|
|
||||||
| SourceGenerators | `GFramework.SourceGenerators/` | `docs/zh-CN/api-reference/source-generators/` |
|
|
||||||
|
|
||||||
### 命名空间映射
|
|
||||||
|
|
||||||
- `GFramework.Core.*` → Core 模块
|
|
||||||
- `GFramework.Game.*` → Game 模块
|
|
||||||
- `GFramework.Godot.*` → Godot 模块
|
|
||||||
- `GFramework.SourceGenerators.*` → SourceGenerators 模块
|
|
||||||
|
|
||||||
## 过滤规则
|
|
||||||
|
|
||||||
### 包含的文件
|
|
||||||
|
|
||||||
- 公共类(public class)
|
|
||||||
- 公共接口(public interface)
|
|
||||||
- 公共枚举(public enum)
|
|
||||||
- 公共结构体(public struct)
|
|
||||||
|
|
||||||
### 排除的文件
|
|
||||||
|
|
||||||
- 内部类型(internal)
|
|
||||||
- 生成的代码(`*.g.cs`、`*.Designer.cs`)
|
|
||||||
- 测试文件(`*.Tests.cs`、`*Test.cs`)
|
|
||||||
- 临时文件(`*.tmp.cs`)
|
|
||||||
- 编译器生成的文件(`AssemblyInfo.cs`)
|
|
||||||
|
|
||||||
### 排除的类型
|
|
||||||
|
|
||||||
- 编译器生成的类型(`<>c__DisplayClass`)
|
|
||||||
- 匿名类型
|
|
||||||
- 嵌套的私有类型
|
|
||||||
|
|
||||||
## 批量处理脚本
|
|
||||||
|
|
||||||
### batch-generate.sh
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# 批量生成 API 文档
|
|
||||||
# 用法: batch-generate.sh <模块名>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
MODULE="$1"
|
|
||||||
|
|
||||||
if [ -z "$MODULE" ]; then
|
|
||||||
echo "用法: $0 <模块名>"
|
|
||||||
echo "可用模块: Core, Game, Godot, SourceGenerators"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 确定源代码目录
|
|
||||||
case "$MODULE" in
|
|
||||||
Core)
|
|
||||||
SOURCE_DIR="GFramework.Core"
|
|
||||||
;;
|
|
||||||
Game)
|
|
||||||
SOURCE_DIR="GFramework.Game"
|
|
||||||
;;
|
|
||||||
Godot)
|
|
||||||
SOURCE_DIR="GFramework.Godot"
|
|
||||||
;;
|
|
||||||
SourceGenerators)
|
|
||||||
SOURCE_DIR="GFramework.SourceGenerators"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "错误: 未知的模块: $MODULE"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ! -d "$SOURCE_DIR" ]; then
|
|
||||||
echo "错误: 源代码目录不存在: $SOURCE_DIR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "批量生成 $MODULE 模块的 API 文档"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 查找所有 C# 文件
|
|
||||||
FILES=$(find "$SOURCE_DIR" -name "*.cs" -type f \
|
|
||||||
! -name "*.g.cs" \
|
|
||||||
! -name "*.Designer.cs" \
|
|
||||||
! -name "*Test.cs" \
|
|
||||||
! -name "*.Tests.cs" \
|
|
||||||
! -name "AssemblyInfo.cs")
|
|
||||||
|
|
||||||
FILE_COUNT=$(echo "$FILES" | wc -l)
|
|
||||||
echo "找到 $FILE_COUNT 个文件"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
GENERATED=0
|
|
||||||
SKIPPED=0
|
|
||||||
FAILED=0
|
|
||||||
|
|
||||||
for FILE in $FILES; do
|
|
||||||
echo "处理: $FILE"
|
|
||||||
|
|
||||||
# 检查是否包含公共类型
|
|
||||||
if ! grep -q "public \(class\|interface\|enum\|struct\)" "$FILE"; then
|
|
||||||
echo " ⊘ 跳过(无公共类型)"
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 调用 vitepress-api-doc(由 AI 执行)
|
|
||||||
# /vitepress-api-doc "$FILE"
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo " ✓ 生成成功"
|
|
||||||
GENERATED=$((GENERATED + 1))
|
|
||||||
else
|
|
||||||
echo " ✗ 生成失败"
|
|
||||||
FAILED=$((FAILED + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "批量生成完成"
|
|
||||||
echo "=========================================="
|
|
||||||
echo "总文件数: $FILE_COUNT"
|
|
||||||
echo "生成成功: $GENERATED"
|
|
||||||
echo "跳过: $SKIPPED"
|
|
||||||
echo "失败: $FAILED"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ $FAILED -eq 0 ]; then
|
|
||||||
echo "✓ 所有文档生成成功"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "✗ 部分文档生成失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置选项
|
|
||||||
|
|
||||||
### 过滤选项
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 包含内部类型
|
|
||||||
/vitepress-batch-api Core --include-internal
|
|
||||||
|
|
||||||
# 包含生成的代码
|
|
||||||
/vitepress-batch-api Core --include-generated
|
|
||||||
|
|
||||||
# 自定义过滤规则
|
|
||||||
/vitepress-batch-api Core --exclude "*.Tests.cs" --exclude "*.g.cs"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 输出选项
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 指定输出目录
|
|
||||||
/vitepress-batch-api Core --output docs/zh-CN/api-reference/core/
|
|
||||||
|
|
||||||
# 覆盖现有文档
|
|
||||||
/vitepress-batch-api Core --force
|
|
||||||
|
|
||||||
# 仅生成索引页
|
|
||||||
/vitepress-batch-api Core --index-only
|
|
||||||
```
|
|
||||||
|
|
||||||
### 并行处理
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 并行生成(加快速度)
|
|
||||||
/vitepress-batch-api Core --parallel 4
|
|
||||||
```
|
|
||||||
|
|
||||||
## 进度显示
|
|
||||||
|
|
||||||
### 实时进度
|
|
||||||
|
|
||||||
```
|
|
||||||
========================================
|
|
||||||
批量生成 Core 模块的 API 文档
|
|
||||||
========================================
|
|
||||||
|
|
||||||
找到 45 个文件
|
|
||||||
|
|
||||||
[1/45] 处理: GFramework.Core/architecture/Architecture.cs
|
|
||||||
✓ 生成成功
|
|
||||||
|
|
||||||
[2/45] 处理: GFramework.Core/architecture/IArchitecture.cs
|
|
||||||
✓ 生成成功
|
|
||||||
|
|
||||||
[3/45] 处理: GFramework.Core/command/Command.cs
|
|
||||||
⊘ 跳过(无公共类型)
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
[45/45] 处理: GFramework.Core/utility/Utility.cs
|
|
||||||
✓ 生成成功
|
|
||||||
|
|
||||||
========================================
|
|
||||||
批量生成完成
|
|
||||||
========================================
|
|
||||||
总文件数: 45
|
|
||||||
生成成功: 38
|
|
||||||
跳过: 5
|
|
||||||
失败: 2
|
|
||||||
|
|
||||||
✗ 部分文档生成失败
|
|
||||||
|
|
||||||
失败的文件:
|
|
||||||
- GFramework.Core/internal/InternalClass.cs (缺少 XML 注释)
|
|
||||||
- GFramework.Core/legacy/LegacyClass.cs (解析错误)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
1. 模块源代码目录存在
|
|
||||||
2. 源代码文件包含 XML 文档注释
|
|
||||||
3. 有足够的磁盘空间存储生成的文档
|
|
||||||
|
|
||||||
## 相关 Skills
|
|
||||||
|
|
||||||
- `/vitepress-api-doc` - 单文件 API 文档生成
|
|
||||||
- `/vitepress-validate` - 验证生成的文档
|
|
||||||
- `/vitepress-guide` - 生成功能指南
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **首次生成**:使用批量生成快速创建所有文档
|
|
||||||
2. **增量更新**:修改代码后使用单文件生成更新对应文档
|
|
||||||
3. **定期验证**:批量生成后运行验证确保质量
|
|
||||||
4. **版本控制**:将生成的文档提交到版本控制系统
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:部分文件生成失败
|
|
||||||
**解决方案**:检查失败文件的 XML 注释是否完整,手动修复后重新生成
|
|
||||||
|
|
||||||
### 问题:生成速度慢
|
|
||||||
**解决方案**:使用 `--parallel` 选项启用并行处理
|
|
||||||
|
|
||||||
### 问题:生成的文档过多
|
|
||||||
**解决方案**:使用过滤选项排除不需要的文件
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 - 初始版本,支持批量 API 文档生成
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 批量生成 API 文档
|
|
||||||
# 用法: batch-generate.sh <模块名>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
# shellcheck source=../../_shared/module-config.sh
|
|
||||||
source "$SCRIPT_DIR/../../_shared/module-config.sh"
|
|
||||||
|
|
||||||
MODULE="$1"
|
|
||||||
|
|
||||||
if [ -z "$MODULE" ]; then
|
|
||||||
echo "用法: $0 <模块名>"
|
|
||||||
echo "可用模块: $(get_all_modules)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 验证模块名
|
|
||||||
if ! is_valid_module "$MODULE"; then
|
|
||||||
echo "错误: 未知的模块: $MODULE"
|
|
||||||
echo "可用模块: $(get_all_modules)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 获取源代码目录
|
|
||||||
SOURCE_DIR=$(get_source_dir "$MODULE")
|
|
||||||
|
|
||||||
if [ ! -d "$SOURCE_DIR" ]; then
|
|
||||||
echo "错误: 源代码目录不存在: $SOURCE_DIR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "批量生成 $MODULE 模块的 API 文档"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 查找所有 C# 文件
|
|
||||||
mapfile -t FILES < <(find "$SOURCE_DIR" -name "*.cs" -type f \
|
|
||||||
! -name "*.g.cs" \
|
|
||||||
! -name "*.Designer.cs" \
|
|
||||||
! -name "*Test.cs" \
|
|
||||||
! -name "*.Tests.cs" \
|
|
||||||
! -name "AssemblyInfo.cs")
|
|
||||||
|
|
||||||
FILE_COUNT=${#FILES[@]}
|
|
||||||
echo "找到 $FILE_COUNT 个文件"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
GENERATED=0
|
|
||||||
SKIPPED=0
|
|
||||||
FAILED=0
|
|
||||||
|
|
||||||
for FILE in "${FILES[@]}"; do
|
|
||||||
echo "处理: $FILE"
|
|
||||||
|
|
||||||
# 检查是否包含公共类型
|
|
||||||
if ! grep -q "public \(class\|interface\|enum\|struct\)" "$FILE"; then
|
|
||||||
echo " ⊘ 跳过(无公共类型)"
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 注意: 实际的文档生成由 AI 调用 /vitepress-api-doc 完成
|
|
||||||
# 此脚本仅用于扫描和过滤文件
|
|
||||||
|
|
||||||
echo " → 待生成"
|
|
||||||
GENERATED=$((GENERATED + 1))
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "扫描完成"
|
|
||||||
echo "=========================================="
|
|
||||||
echo "总文件数: $FILE_COUNT"
|
|
||||||
echo "待生成: $GENERATED"
|
|
||||||
echo "跳过: $SKIPPED"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
name: vitepress-doc-generator
|
|
||||||
description: Generate standardized VitePress documentation from source code.
|
|
||||||
disable-model-invocation: true
|
|
||||||
---
|
|
||||||
|
|
||||||
# Role
|
|
||||||
|
|
||||||
You are a technical documentation generator specialized in VitePress.
|
|
||||||
|
|
||||||
# Objective
|
|
||||||
|
|
||||||
Analyze the provided code context and generate a structured VitePress-compatible Markdown document.
|
|
||||||
|
|
||||||
# Output Requirements
|
|
||||||
|
|
||||||
1. Output MUST be valid Markdown only.
|
|
||||||
2. Include frontmatter:
|
|
||||||
|
|
||||||
---
|
|
||||||
title: <Module Name>
|
|
||||||
outline: deep
|
|
||||||
---
|
|
||||||
|
|
||||||
3. No explanations.
|
|
||||||
4. No conversational text.
|
|
||||||
5. No emoji.
|
|
||||||
6. Use Chinese.
|
|
||||||
7. Use structured headings.
|
|
||||||
|
|
||||||
# Required Structure
|
|
||||||
|
|
||||||
# 模块概述
|
|
||||||
- 模块职责
|
|
||||||
- 设计目标
|
|
||||||
|
|
||||||
# 核心类说明
|
|
||||||
## 类名
|
|
||||||
### 职责
|
|
||||||
### 主要方法
|
|
||||||
### 依赖关系
|
|
||||||
|
|
||||||
# 设计模式分析
|
|
||||||
# 可扩展性说明
|
|
||||||
# 使用示例(如适用)
|
|
||||||
|
|
||||||
# Self-Validation
|
|
||||||
|
|
||||||
Before returning output, verify:
|
|
||||||
- Frontmatter exists
|
|
||||||
- All required sections exist
|
|
||||||
- No extra commentary text
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
# VitePress 功能指南生成
|
|
||||||
|
|
||||||
生成功能模块的使用指南文档,包括概念说明、用法示例和最佳实践。
|
|
||||||
|
|
||||||
## 用途
|
|
||||||
|
|
||||||
此 skill 用于生成结构化的功能指南文档,适用于:
|
|
||||||
- 核心功能模块的使用说明
|
|
||||||
- 设计模式和架构概念
|
|
||||||
- 系统功能的详细介绍
|
|
||||||
- 最佳实践和常见问题
|
|
||||||
|
|
||||||
## 调用方式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/vitepress-guide <主题> <目标模块>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-guide "事件系统" Core
|
|
||||||
/vitepress-guide "IoC 容器" Core
|
|
||||||
/vitepress-guide "Godot 节点扩展" Godot
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **收集需求**
|
|
||||||
- 询问用户指南主题
|
|
||||||
- 确定目标受众(初学者/进阶/专家)
|
|
||||||
- 了解重点内容(概念/用法/最佳实践)
|
|
||||||
|
|
||||||
2. **搜索相关资源**
|
|
||||||
- 搜索相关代码文件
|
|
||||||
- 查找现有文档
|
|
||||||
- 识别相关类型和接口
|
|
||||||
|
|
||||||
3. **生成指南结构**
|
|
||||||
- 根据 `template.md` 创建文档框架
|
|
||||||
- 填充概述和核心概念
|
|
||||||
- 添加基本用法和高级用法
|
|
||||||
- 补充最佳实践和常见问题
|
|
||||||
|
|
||||||
4. **生成代码示例**
|
|
||||||
- 基本用法示例(最简单的场景)
|
|
||||||
- 常见场景示例(实际应用)
|
|
||||||
- 高级用法示例(复杂配置)
|
|
||||||
|
|
||||||
5. **确定输出路径**
|
|
||||||
- 保存到 `docs/zh-CN/<模块>/`
|
|
||||||
- 文件名使用小写加连字符(如 `event-system.md`)
|
|
||||||
|
|
||||||
6. **更新导航配置**
|
|
||||||
- 在 VitePress 侧边栏中添加新指南
|
|
||||||
|
|
||||||
## 输出规范
|
|
||||||
|
|
||||||
### Frontmatter 格式
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 指南标题
|
|
||||||
description: 简短描述(1-2 句话)
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 文档结构
|
|
||||||
|
|
||||||
1. **概述**:功能的简介和用途
|
|
||||||
2. **核心概念**:关键概念和术语解释
|
|
||||||
3. **基本用法**:最简单的使用方式
|
|
||||||
4. **高级用法**:复杂场景和配置
|
|
||||||
5. **最佳实践**:推荐的使用方式
|
|
||||||
6. **常见问题**:FAQ 和故障排除
|
|
||||||
|
|
||||||
### 章节示例
|
|
||||||
|
|
||||||
**概述**:
|
|
||||||
```markdown
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
事件系统提供了一种松耦合的组件间通信机制。通过事件,不同的组件可以在不直接引用彼此的情况下进行交互。
|
|
||||||
|
|
||||||
**主要特性**:
|
|
||||||
- 类型安全的事件
|
|
||||||
- 自动内存管理
|
|
||||||
- 支持事件优先级
|
|
||||||
- 线程安全
|
|
||||||
```
|
|
||||||
|
|
||||||
**核心概念**:
|
|
||||||
```markdown
|
|
||||||
## 核心概念
|
|
||||||
|
|
||||||
### 事件类型
|
|
||||||
|
|
||||||
事件是一个普通的 C# 类,用于携带事件数据:
|
|
||||||
|
|
||||||
\`\`\`csharp
|
|
||||||
public class PlayerDiedEvent
|
|
||||||
{
|
|
||||||
public int PlayerId { get; set; }
|
|
||||||
public string Reason { get; set; }
|
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
### 事件发送
|
|
||||||
|
|
||||||
通过架构发送事件:
|
|
||||||
|
|
||||||
\`\`\`csharp
|
|
||||||
this.SendEvent(new PlayerDiedEvent
|
|
||||||
{
|
|
||||||
PlayerId = 1,
|
|
||||||
Reason = "Fall damage"
|
|
||||||
});
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
### 事件监听
|
|
||||||
|
|
||||||
注册事件监听器:
|
|
||||||
|
|
||||||
\`\`\`csharp
|
|
||||||
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
## 模板变量
|
|
||||||
|
|
||||||
- `{{GUIDE_TITLE}}` - 指南标题
|
|
||||||
- `{{GUIDE_DESCRIPTION}}` - 简短描述
|
|
||||||
- `{{OVERVIEW}}` - 概述内容
|
|
||||||
- `{{CORE_CONCEPTS}}` - 核心概念
|
|
||||||
- `{{BASIC_USAGE}}` - 基本用法
|
|
||||||
- `{{ADVANCED_USAGE}}` - 高级用法
|
|
||||||
- `{{BEST_PRACTICES}}` - 最佳实践
|
|
||||||
- `{{FAQ}}` - 常见问题
|
|
||||||
|
|
||||||
## 示例输出
|
|
||||||
|
|
||||||
参考 `examples/guide-example.md`,该示例基于现有的 IoC 容器文档创建。
|
|
||||||
|
|
||||||
## 内容要求
|
|
||||||
|
|
||||||
### 概述部分
|
|
||||||
- 1-2 段简介
|
|
||||||
- 列出主要特性(3-5 个)
|
|
||||||
- 说明适用场景
|
|
||||||
|
|
||||||
### 核心概念部分
|
|
||||||
- 使用三级标题(###)分隔不同概念
|
|
||||||
- 每个概念包含简短说明和代码示例
|
|
||||||
- 解释关键术语
|
|
||||||
|
|
||||||
### 基本用法部分
|
|
||||||
- 提供完整的可运行示例
|
|
||||||
- 从最简单的场景开始
|
|
||||||
- 逐步增加复杂度
|
|
||||||
- 包含必要的 using 语句
|
|
||||||
|
|
||||||
### 高级用法部分
|
|
||||||
- 展示复杂场景
|
|
||||||
- 说明配置选项
|
|
||||||
- 提供性能优化建议
|
|
||||||
|
|
||||||
### 最佳实践部分
|
|
||||||
- 使用编号列表
|
|
||||||
- 每条实践包含简短说明
|
|
||||||
- 提供正反示例(✓ 推荐 / ✗ 不推荐)
|
|
||||||
|
|
||||||
### 常见问题部分
|
|
||||||
- 使用问答格式
|
|
||||||
- 提供具体的解决方案
|
|
||||||
- 包含相关链接
|
|
||||||
|
|
||||||
## 写作风格
|
|
||||||
|
|
||||||
### 语气
|
|
||||||
- 友好、专业
|
|
||||||
- 使用第二人称("你")
|
|
||||||
- 避免过于技术化的术语
|
|
||||||
|
|
||||||
### 代码示例
|
|
||||||
- 完整且可运行
|
|
||||||
- 包含注释说明关键步骤
|
|
||||||
- 使用有意义的变量名
|
|
||||||
- 遵循项目代码风格
|
|
||||||
|
|
||||||
### 格式
|
|
||||||
- 使用 Markdown 标准格式
|
|
||||||
- 代码块使用语法高亮
|
|
||||||
- 重要内容使用粗体或引用块
|
|
||||||
- 适当使用列表和表格
|
|
||||||
|
|
||||||
## 配置选项
|
|
||||||
|
|
||||||
### 目标受众
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 初学者(更多解释,简单示例)
|
|
||||||
/vitepress-guide "事件系统" Core --audience beginner
|
|
||||||
|
|
||||||
# 进阶(平衡解释和示例)
|
|
||||||
/vitepress-guide "事件系统" Core --audience intermediate
|
|
||||||
|
|
||||||
# 专家(简洁说明,复杂示例)
|
|
||||||
/vitepress-guide "事件系统" Core --audience expert
|
|
||||||
```
|
|
||||||
|
|
||||||
### 重点内容
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 侧重概念
|
|
||||||
/vitepress-guide "事件系统" Core --focus concepts
|
|
||||||
|
|
||||||
# 侧重用法
|
|
||||||
/vitepress-guide "事件系统" Core --focus usage
|
|
||||||
|
|
||||||
# 侧重最佳实践
|
|
||||||
/vitepress-guide "事件系统" Core --focus best-practices
|
|
||||||
```
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
1. 了解指南主题的基本概念
|
|
||||||
2. 能够访问相关代码文件
|
|
||||||
3. 了解项目的代码风格和术语
|
|
||||||
|
|
||||||
## 相关 Skills
|
|
||||||
|
|
||||||
- `/vitepress-api-doc` - 生成 API 参考文档
|
|
||||||
- `/vitepress-tutorial` - 生成分步教程
|
|
||||||
- `/vitepress-validate` - 验证生成的文档
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **先搜索后编写**:查看现有文档和代码,保持一致性
|
|
||||||
2. **使用真实示例**:基于项目实际代码创建示例
|
|
||||||
3. **保持简洁**:每个章节聚焦一个主题
|
|
||||||
4. **提供完整代码**:确保示例可以直接运行
|
|
||||||
5. **添加交叉引用**:链接到相关的 API 文档和其他指南
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:不确定指南应该包含哪些内容
|
|
||||||
**解决方案**:参考 `examples/guide-example.md` 和现有的指南文档
|
|
||||||
|
|
||||||
### 问题:代码示例过于复杂
|
|
||||||
**解决方案**:将复杂示例拆分为多个简单示例,逐步增加复杂度
|
|
||||||
|
|
||||||
### 问题:概念解释不清晰
|
|
||||||
**解决方案**:使用类比、图表或分步说明来辅助解释
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 - 初始版本,支持功能指南生成
|
|
||||||
@ -1,283 +0,0 @@
|
|||||||
---
|
|
||||||
title: IoC 容器使用指南
|
|
||||||
description: IoC(控制反转)容器提供了轻量级的依赖注入功能,用于管理框架中各种组件的注册和获取。
|
|
||||||
---
|
|
||||||
|
|
||||||
# IoC 容器使用指南
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖注入容器,用于管理框架中各种组件的注册和获取。通过 IoC 容器,可以实现组件间的解耦,便于测试和维护。
|
|
||||||
|
|
||||||
IoC 容器是 GFramework 架构的核心组件之一,为整个框架提供依赖管理和组件解析服务。
|
|
||||||
|
|
||||||
**主要特性**:
|
|
||||||
- 类型安全的依赖管理
|
|
||||||
- 支持单例和多实例注册
|
|
||||||
- 线程安全操作
|
|
||||||
- 容器冻结保护
|
|
||||||
- 自动接口注册
|
|
||||||
|
|
||||||
## 核心概念
|
|
||||||
|
|
||||||
### 依赖注入
|
|
||||||
|
|
||||||
依赖注入是一种设计模式,通过容器管理对象的创建和依赖关系,而不是在代码中直接创建对象。
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 不使用依赖注入
|
|
||||||
public class GameController
|
|
||||||
{
|
|
||||||
private PlayerModel model = new PlayerModel(); // 硬编码依赖
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用依赖注入
|
|
||||||
public class GameController : IController
|
|
||||||
{
|
|
||||||
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
var model = this.GetModel<PlayerModel>(); // 从容器获取
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 容器注册
|
|
||||||
|
|
||||||
在架构初始化时,将组件注册到容器中:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
// 注册 Model
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
|
|
||||||
// 注册 System
|
|
||||||
RegisterSystem(new GameplaySystem());
|
|
||||||
|
|
||||||
// 注册 Utility
|
|
||||||
RegisterUtility(new StorageUtility());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 容器解析
|
|
||||||
|
|
||||||
通过扩展方法从容器中获取已注册的组件:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 在 Controller 中
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
var gameplaySystem = this.GetSystem<GameplaySystem>();
|
|
||||||
var storageUtility = this.GetUtility<StorageUtility>();
|
|
||||||
```
|
|
||||||
|
|
||||||
## 基本用法
|
|
||||||
|
|
||||||
### 注册组件
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var container = new IocContainer();
|
|
||||||
|
|
||||||
// 注册单例(一个类型只能有一个实例)
|
|
||||||
container.RegisterSingleton<IPlayerModel>(new PlayerModel());
|
|
||||||
|
|
||||||
// 注册多实例(一个类型可以有多个实例)
|
|
||||||
container.RegisterPlurality<IEnemy>(new Goblin());
|
|
||||||
container.RegisterPlurality<IEnemy>(new Orc());
|
|
||||||
container.RegisterPlurality<IEnemy>(new Dragon());
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取组件
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 获取单例
|
|
||||||
var playerModel = container.Get<IPlayerModel>();
|
|
||||||
|
|
||||||
// 获取多实例集合
|
|
||||||
var enemies = container.GetAll<IEnemy>(); // 返回 List<IEnemy>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 在架构中使用
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
// 注册组件
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
RegisterModel(new InventoryModel());
|
|
||||||
RegisterSystem(new GameplaySystem());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 在 Controller 中使用
|
|
||||||
public class GameController : IController
|
|
||||||
{
|
|
||||||
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
// 通过扩展方法获取组件
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
var inventoryModel = this.GetModel<InventoryModel>();
|
|
||||||
var gameplaySystem = this.GetSystem<GameplaySystem>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 高级用法
|
|
||||||
|
|
||||||
### 容器冻结
|
|
||||||
|
|
||||||
容器在架构初始化完成后会被冻结,防止运行时修改:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var container = new IocContainer();
|
|
||||||
container.Register<IPlayerModel>(new PlayerModel());
|
|
||||||
|
|
||||||
// 冻结容器
|
|
||||||
container.Freeze();
|
|
||||||
|
|
||||||
// 以下操作会抛出 InvalidOperationException
|
|
||||||
// container.Register<IGameSystem>(new GameSystem());
|
|
||||||
```
|
|
||||||
|
|
||||||
### 多实例管理
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 注册多个同类型实例
|
|
||||||
container.RegisterPlurality<IWeapon>(new Sword());
|
|
||||||
container.RegisterPlurality<IWeapon>(new Bow());
|
|
||||||
container.RegisterPlurality<IWeapon>(new Staff());
|
|
||||||
|
|
||||||
// 获取所有实例
|
|
||||||
var allWeapons = container.GetAll<IWeapon>();
|
|
||||||
foreach (var weapon in allWeapons)
|
|
||||||
{
|
|
||||||
weapon.Attack();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 接口自动注册
|
|
||||||
|
|
||||||
注册实例时,容器会自动将其注册到所有实现的接口:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class PlayerModel : IModel, IPlayerModel, IDisposable
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册实例
|
|
||||||
container.Register<PlayerModel>(new PlayerModel());
|
|
||||||
|
|
||||||
// 可以通过任何接口获取
|
|
||||||
var model1 = container.Get<IModel>();
|
|
||||||
var model2 = container.Get<IPlayerModel>();
|
|
||||||
var model3 = container.Get<IDisposable>();
|
|
||||||
// 以上三个变量指向同一个实例
|
|
||||||
```
|
|
||||||
|
|
||||||
### 线程安全操作
|
|
||||||
|
|
||||||
容器的所有操作都是线程安全的:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 多线程环境下安全使用
|
|
||||||
Parallel.For(0, 100, i =>
|
|
||||||
{
|
|
||||||
var model = container.Get<IPlayerModel>();
|
|
||||||
model.DoSomething();
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **使用接口注册**:优先使用接口类型注册,而不是具体类型
|
|
||||||
```csharp
|
|
||||||
✓ container.Register<IPlayerModel>(new PlayerModel());
|
|
||||||
✗ container.Register<PlayerModel>(new PlayerModel());
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **单例 vs 多实例**:根据需求选择合适的注册方式
|
|
||||||
- 单例:全局唯一的服务(如配置、管理器)
|
|
||||||
- 多实例:可以有多个实例的对象(如敌人、道具)
|
|
||||||
|
|
||||||
3. **避免循环依赖**:组件之间不应该相互依赖
|
|
||||||
```csharp
|
|
||||||
✗ System A 依赖 System B,System B 又依赖 System A
|
|
||||||
✓ 使用事件系统进行通信,避免直接依赖
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **在 Init 中注册**:所有组件应该在架构的 `Init()` 方法中注册
|
|
||||||
```csharp
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
// 在这里注册所有组件
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
RegisterSystem(new GameplaySystem());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **使用扩展方法**:通过扩展方法获取组件,代码更简洁
|
|
||||||
```csharp
|
|
||||||
✓ var model = this.GetModel<PlayerModel>();
|
|
||||||
✗ var model = this.GetArchitecture().GetModel<PlayerModel>();
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **不要在运行时注册**:容器冻结后不应该再注册新组件
|
|
||||||
```csharp
|
|
||||||
✗ 在游戏运行时动态注册组件
|
|
||||||
✓ 在架构初始化时注册所有需要的组件
|
|
||||||
```
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### 问题:如何判断使用单例还是多实例?
|
|
||||||
|
|
||||||
**解答**:
|
|
||||||
- 使用单例(`RegisterSingleton`):全局唯一的服务,如 PlayerModel、GameConfiguration
|
|
||||||
- 使用多实例(`RegisterPlurality`):可以有多个实例的对象,如 Enemy、Weapon
|
|
||||||
|
|
||||||
### 问题:容器冻结后如何添加新组件?
|
|
||||||
|
|
||||||
**解答**:
|
|
||||||
容器冻结是为了保护架构稳定性。如果需要动态添加组件,应该:
|
|
||||||
1. 在架构初始化时预先注册所有可能需要的组件
|
|
||||||
2. 使用对象池模式管理动态对象
|
|
||||||
3. 考虑使用工厂模式创建临时对象
|
|
||||||
|
|
||||||
### 问题:如何处理组件的生命周期?
|
|
||||||
|
|
||||||
**解答**:
|
|
||||||
- 实现 `IDisposable` 接口的组件会在架构销毁时自动释放
|
|
||||||
- 架构会按注册的逆序销毁组件
|
|
||||||
- 不需要手动管理组件的生命周期
|
|
||||||
|
|
||||||
### 问题:可以在容器中注册值类型吗?
|
|
||||||
|
|
||||||
**解答**:
|
|
||||||
可以,但会发生装箱。建议将值类型包装在类中:
|
|
||||||
```csharp
|
|
||||||
// 不推荐
|
|
||||||
container.Register<int>(42);
|
|
||||||
|
|
||||||
// 推荐
|
|
||||||
public class GameConfig
|
|
||||||
{
|
|
||||||
public int MaxPlayers { get; set; } = 42;
|
|
||||||
}
|
|
||||||
container.Register<GameConfig>(new GameConfig());
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
|
||||||
|
|
||||||
- [架构组件](/zh-CN/core/architecture) - 架构基础
|
|
||||||
- [Model 层](/zh-CN/core/model) - 数据模型
|
|
||||||
- [System 层](/zh-CN/core/system) - 业务系统
|
|
||||||
- [Utility 工具类](/zh-CN/core/utility) - 工具类
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
title: {{GUIDE_TITLE}}
|
|
||||||
description: {{GUIDE_DESCRIPTION}}
|
|
||||||
---
|
|
||||||
|
|
||||||
# {{GUIDE_TITLE}}
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
{{OVERVIEW}}
|
|
||||||
|
|
||||||
## 核心概念
|
|
||||||
|
|
||||||
{{CORE_CONCEPTS}}
|
|
||||||
|
|
||||||
## 基本用法
|
|
||||||
|
|
||||||
{{BASIC_USAGE}}
|
|
||||||
|
|
||||||
## 高级用法
|
|
||||||
|
|
||||||
{{ADVANCED_USAGE}}
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
{{BEST_PRACTICES}}
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
{{FAQ}}
|
|
||||||
|
|
||||||
## 相关文档
|
|
||||||
|
|
||||||
{{RELATED_DOCS}}
|
|
||||||
@ -1,253 +0,0 @@
|
|||||||
# VitePress 教程生成
|
|
||||||
|
|
||||||
生成分步教程文档,适合初学者学习框架功能。
|
|
||||||
|
|
||||||
## 用途
|
|
||||||
|
|
||||||
此 skill 用于生成结构化的分步教程,适用于:
|
|
||||||
- 框架入门教程
|
|
||||||
- 功能实现教程
|
|
||||||
- 最佳实践演示
|
|
||||||
- 问题解决方案
|
|
||||||
|
|
||||||
## 调用方式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/vitepress-tutorial <教程主题>
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-tutorial "创建第一个 System"
|
|
||||||
/vitepress-tutorial "实现自定义命令"
|
|
||||||
/vitepress-tutorial "使用事件系统"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **收集需求**
|
|
||||||
- 询问用户教程主题
|
|
||||||
- 确定学习目标
|
|
||||||
- 了解前置知识要求
|
|
||||||
|
|
||||||
2. **设计教程步骤**
|
|
||||||
- 将任务分解为 3-7 个步骤
|
|
||||||
- 每步聚焦一个具体任务
|
|
||||||
- 确保步骤之间逻辑连贯
|
|
||||||
|
|
||||||
3. **生成教程内容**
|
|
||||||
- 根据 `template.md` 创建文档框架
|
|
||||||
- 为每步编写详细说明和代码
|
|
||||||
- 添加完整的可运行代码
|
|
||||||
- 说明预期结果
|
|
||||||
|
|
||||||
4. **确定输出路径**
|
|
||||||
- 保存到 `docs/zh-CN/tutorials/`
|
|
||||||
- 文件名使用小写加连字符
|
|
||||||
|
|
||||||
5. **更新导航配置**
|
|
||||||
- 在 VitePress 侧边栏中添加新教程
|
|
||||||
|
|
||||||
## 输出规范
|
|
||||||
|
|
||||||
### Frontmatter 格式
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 教程标题
|
|
||||||
description: 简短描述(1 句话说明学习内容)
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 文档结构
|
|
||||||
|
|
||||||
1. **学习目标**:完成教程后能够掌握的技能
|
|
||||||
2. **前置条件**:需要的前置知识和环境
|
|
||||||
3. **步骤 1-N**:分步说明(3-7 步)
|
|
||||||
4. **完整代码**:汇总所有代码
|
|
||||||
5. **运行结果**:预期输出和效果
|
|
||||||
6. **下一步**:后续学习建议
|
|
||||||
|
|
||||||
### 步骤格式
|
|
||||||
|
|
||||||
每个步骤应包含:
|
|
||||||
- 步骤标题(简短、动词开头)
|
|
||||||
- 步骤说明(为什么要这样做)
|
|
||||||
- 代码示例(完整且可运行)
|
|
||||||
- 代码解释(关键部分的说明)
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```markdown
|
|
||||||
## 步骤 1:创建 Model 类
|
|
||||||
|
|
||||||
首先,我们需要创建一个 Model 来存储玩家数据。Model 负责管理应用的数据和状态。
|
|
||||||
|
|
||||||
\`\`\`csharp
|
|
||||||
using GFramework.Core.Abstractions.model;
|
|
||||||
using GFramework.Core.Abstractions.property;
|
|
||||||
|
|
||||||
public class PlayerModel : IModel
|
|
||||||
{
|
|
||||||
// 玩家名称(可绑定属性)
|
|
||||||
public BindableProperty<string> Name { get; } = new("Player");
|
|
||||||
|
|
||||||
// 玩家生命值
|
|
||||||
public BindableProperty<int> Health { get; } = new(100);
|
|
||||||
|
|
||||||
// 玩家金币
|
|
||||||
public BindableProperty<int> Gold { get; } = new(0);
|
|
||||||
|
|
||||||
public void Init() { }
|
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
**代码说明**:
|
|
||||||
- `BindableProperty<T>` 是可绑定属性,值变化时会自动通知监听者
|
|
||||||
- `Init()` 方法在 Model 注册到架构时被调用
|
|
||||||
- 使用属性初始化器设置默认值
|
|
||||||
```
|
|
||||||
|
|
||||||
## 模板变量
|
|
||||||
|
|
||||||
- `{{TUTORIAL_TITLE}}` - 教程标题
|
|
||||||
- `{{TUTORIAL_DESCRIPTION}}` - 简短描述
|
|
||||||
- `{{LEARNING_OBJECTIVES}}` - 学习目标
|
|
||||||
- `{{PREREQUISITES}}` - 前置条件
|
|
||||||
- `{{STEP_N_TITLE}}` - 步骤标题
|
|
||||||
- `{{STEP_N_CONTENT}}` - 步骤内容
|
|
||||||
- `{{FULL_CODE}}` - 完整代码
|
|
||||||
- `{{EXPECTED_OUTPUT}}` - 预期输出
|
|
||||||
- `{{NEXT_STEPS}}` - 下一步建议
|
|
||||||
|
|
||||||
## 示例输出
|
|
||||||
|
|
||||||
参考 `examples/tutorial-example.md`,该示例基于现有的教程文档创建。
|
|
||||||
|
|
||||||
## 内容要求
|
|
||||||
|
|
||||||
### 学习目标
|
|
||||||
- 使用列表格式
|
|
||||||
- 3-5 个具体的学习目标
|
|
||||||
- 使用"能够..."句式
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```markdown
|
|
||||||
## 学习目标
|
|
||||||
|
|
||||||
完成本教程后,你将能够:
|
|
||||||
- 创建自定义的 Model 类
|
|
||||||
- 在架构中注册 Model
|
|
||||||
- 从 Controller 中访问 Model
|
|
||||||
- 使用可绑定属性管理数据
|
|
||||||
```
|
|
||||||
|
|
||||||
### 前置条件
|
|
||||||
- 列出必需的知识
|
|
||||||
- 说明环境要求
|
|
||||||
- 提供相关文档链接
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```markdown
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
- 已安装 GFramework.Core NuGet 包
|
|
||||||
- 了解 C# 基础语法
|
|
||||||
- 阅读过[架构概览](/zh-CN/getting-started)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤内容
|
|
||||||
- 每步 100-300 字说明
|
|
||||||
- 包含完整的代码示例
|
|
||||||
- 解释关键代码的作用
|
|
||||||
- 使用注释标注重要部分
|
|
||||||
|
|
||||||
### 完整代码
|
|
||||||
- 汇总所有步骤的代码
|
|
||||||
- 确保可以直接复制运行
|
|
||||||
- 包含必要的 using 语句
|
|
||||||
- 添加文件结构说明
|
|
||||||
|
|
||||||
### 运行结果
|
|
||||||
- 描述预期的输出
|
|
||||||
- 如果有界面,提供截图或描述
|
|
||||||
- 说明如何验证结果正确
|
|
||||||
|
|
||||||
### 下一步
|
|
||||||
- 推荐 2-3 个后续教程
|
|
||||||
- 提供相关文档链接
|
|
||||||
- 建议进阶学习方向
|
|
||||||
|
|
||||||
## 写作风格
|
|
||||||
|
|
||||||
### 语气
|
|
||||||
- 友好、鼓励性
|
|
||||||
- 使用第二人称("你")
|
|
||||||
- 避免假设读者已有高级知识
|
|
||||||
|
|
||||||
### 步骤说明
|
|
||||||
- 使用主动语态
|
|
||||||
- 步骤标题使用动词开头
|
|
||||||
- 说明"为什么"而不仅是"怎么做"
|
|
||||||
|
|
||||||
### 代码示例
|
|
||||||
- 完整且可运行
|
|
||||||
- 包含详细注释
|
|
||||||
- 使用有意义的变量名
|
|
||||||
- 遵循项目代码风格
|
|
||||||
|
|
||||||
## 配置选项
|
|
||||||
|
|
||||||
### 教程难度
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 初学者(更多解释,简单示例)
|
|
||||||
/vitepress-tutorial "创建第一个 System" --level beginner
|
|
||||||
|
|
||||||
# 中级(平衡解释和复杂度)
|
|
||||||
/vitepress-tutorial "实现自定义命令" --level intermediate
|
|
||||||
|
|
||||||
# 高级(简洁说明,复杂示例)
|
|
||||||
/vitepress-tutorial "架构模块开发" --level advanced
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤数量
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 指定步骤数量(3-7 步)
|
|
||||||
/vitepress-tutorial "使用事件系统" --steps 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
1. 了解教程主题的基本概念
|
|
||||||
2. 能够访问相关代码文件
|
|
||||||
3. 了解目标受众的知识水平
|
|
||||||
|
|
||||||
## 相关 Skills
|
|
||||||
|
|
||||||
- `/vitepress-api-doc` - 生成 API 参考文档
|
|
||||||
- `/vitepress-guide` - 生成功能指南
|
|
||||||
- `/vitepress-validate` - 验证生成的文档
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **从简单开始**:第一步应该是最简单的操作
|
|
||||||
2. **逐步增加复杂度**:每步在前一步基础上增加新内容
|
|
||||||
3. **提供完整代码**:确保每步的代码都可以运行
|
|
||||||
4. **解释关键概念**:不要假设读者已经了解所有术语
|
|
||||||
5. **测试教程**:确保按照步骤操作能够得到预期结果
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:步骤过多,教程太长
|
|
||||||
**解决方案**:将教程拆分为多个小教程,或合并相似的步骤
|
|
||||||
|
|
||||||
### 问题:代码示例不完整
|
|
||||||
**解决方案**:在"完整代码"章节提供所有文件的完整代码
|
|
||||||
|
|
||||||
### 问题:读者反馈步骤不清晰
|
|
||||||
**解决方案**:增加更多说明,使用截图或图表辅助
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 - 初始版本,支持分步教程生成
|
|
||||||
@ -1,347 +0,0 @@
|
|||||||
---
|
|
||||||
title: 创建第一个 Model
|
|
||||||
description: 学习如何创建和使用 Model 来管理应用数据
|
|
||||||
---
|
|
||||||
|
|
||||||
# 创建第一个 Model
|
|
||||||
|
|
||||||
## 学习目标
|
|
||||||
|
|
||||||
完成本教程后,你将能够:
|
|
||||||
- 理解 Model 在架构中的作用
|
|
||||||
- 创建自定义的 Model 类
|
|
||||||
- 在架构中注册 Model
|
|
||||||
- 从 Controller 中访问 Model
|
|
||||||
- 使用可绑定属性管理数据
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
- 已安装 GFramework.Core NuGet 包
|
|
||||||
- 了解 C# 基础语法
|
|
||||||
- 阅读过[架构概览](/zh-CN/getting-started)
|
|
||||||
|
|
||||||
## 步骤 1:创建 Model 类
|
|
||||||
|
|
||||||
首先,我们需要创建一个 Model 来存储玩家数据。Model 负责管理应用的数据和状态。
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.Abstractions.model;
|
|
||||||
using GFramework.Core.Abstractions.property;
|
|
||||||
|
|
||||||
namespace MyGame.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 玩家数据模型
|
|
||||||
/// </summary>
|
|
||||||
public class PlayerModel : IModel
|
|
||||||
{
|
|
||||||
// 玩家名称(可绑定属性)
|
|
||||||
public BindableProperty<string> Name { get; } = new("Player");
|
|
||||||
|
|
||||||
// 玩家生命值
|
|
||||||
public BindableProperty<int> Health { get; } = new(100);
|
|
||||||
|
|
||||||
// 玩家金币
|
|
||||||
public BindableProperty<int> Gold { get; } = new(0);
|
|
||||||
|
|
||||||
// 玩家等级
|
|
||||||
public BindableProperty<int> Level { get; } = new(1);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Model 初始化方法
|
|
||||||
/// </summary>
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
// 在这里可以进行初始化操作
|
|
||||||
// 例如:从配置文件加载默认值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**代码说明**:
|
|
||||||
- `IModel` 接口标识这是一个数据模型
|
|
||||||
- `BindableProperty<T>` 是可绑定属性,值变化时会自动通知监听者
|
|
||||||
- `Init()` 方法在 Model 注册到架构时被调用
|
|
||||||
- 使用属性初始化器设置默认值
|
|
||||||
|
|
||||||
## 步骤 2:在架构中注册 Model
|
|
||||||
|
|
||||||
创建架构类并注册 Model:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.architecture;
|
|
||||||
using MyGame.Models;
|
|
||||||
|
|
||||||
namespace MyGame
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 游戏架构
|
|
||||||
/// </summary>
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
// 单例访问点
|
|
||||||
public static IArchitecture Interface { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化架构
|
|
||||||
/// </summary>
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
Interface = this;
|
|
||||||
|
|
||||||
// 注册 Model
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**代码说明**:
|
|
||||||
- 继承 `Architecture` 基类
|
|
||||||
- 在 `Init()` 方法中注册 Model
|
|
||||||
- 提供静态属性 `Interface` 用于全局访问架构
|
|
||||||
|
|
||||||
## 步骤 3:创建 Controller 访问 Model
|
|
||||||
|
|
||||||
创建 Controller 来使用 Model:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.Abstractions.architecture;
|
|
||||||
using GFramework.Core.Abstractions.controller;
|
|
||||||
using GFramework.Core.extensions;
|
|
||||||
using MyGame.Models;
|
|
||||||
|
|
||||||
namespace MyGame.Controllers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 游戏控制器
|
|
||||||
/// </summary>
|
|
||||||
public class GameController : IController
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取架构实例
|
|
||||||
/// </summary>
|
|
||||||
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化玩家数据
|
|
||||||
/// </summary>
|
|
||||||
public void InitializePlayer()
|
|
||||||
{
|
|
||||||
// 获取 PlayerModel
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
|
|
||||||
// 设置玩家数据
|
|
||||||
playerModel.Name.Value = "勇者";
|
|
||||||
playerModel.Health.Value = 100;
|
|
||||||
playerModel.Gold.Value = 50;
|
|
||||||
playerModel.Level.Value = 1;
|
|
||||||
|
|
||||||
// 监听属性变化
|
|
||||||
playerModel.Health.RegisterOnValueChanged(health =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"玩家生命值变化: {health}");
|
|
||||||
|
|
||||||
if (health <= 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("玩家死亡!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 玩家受到伤害
|
|
||||||
/// </summary>
|
|
||||||
public void TakeDamage(int damage)
|
|
||||||
{
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
playerModel.Health.Value -= damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 玩家获得金币
|
|
||||||
/// </summary>
|
|
||||||
public void AddGold(int amount)
|
|
||||||
{
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
playerModel.Gold.Value += amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**代码说明**:
|
|
||||||
- 实现 `IController` 接口
|
|
||||||
- 通过 `this.GetModel<T>()` 扩展方法获取 Model
|
|
||||||
- 使用 `.Value` 访问和修改属性值
|
|
||||||
- 使用 `RegisterOnValueChanged` 监听属性变化
|
|
||||||
|
|
||||||
## 步骤 4:初始化并使用架构
|
|
||||||
|
|
||||||
在程序入口点初始化架构:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using MyGame;
|
|
||||||
using MyGame.Controllers;
|
|
||||||
|
|
||||||
// 1. 创建并初始化架构
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
architecture.Initialize();
|
|
||||||
|
|
||||||
// 2. 等待架构就绪
|
|
||||||
await architecture.WaitUntilReadyAsync();
|
|
||||||
|
|
||||||
// 3. 创建 Controller 并使用
|
|
||||||
var gameController = new GameController();
|
|
||||||
|
|
||||||
// 初始化玩家
|
|
||||||
gameController.InitializePlayer();
|
|
||||||
|
|
||||||
// 玩家受到伤害
|
|
||||||
gameController.TakeDamage(20);
|
|
||||||
// 输出: 玩家生命值变化: 80
|
|
||||||
|
|
||||||
// 玩家获得金币
|
|
||||||
gameController.AddGold(100);
|
|
||||||
```
|
|
||||||
|
|
||||||
**代码说明**:
|
|
||||||
- 创建架构实例并调用 `Initialize()`
|
|
||||||
- 使用 `WaitUntilReadyAsync()` 等待架构就绪
|
|
||||||
- 创建 Controller 实例并调用方法
|
|
||||||
|
|
||||||
## 完整代码
|
|
||||||
|
|
||||||
### PlayerModel.cs
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.Abstractions.model;
|
|
||||||
using GFramework.Core.Abstractions.property;
|
|
||||||
|
|
||||||
namespace MyGame.Models
|
|
||||||
{
|
|
||||||
public class PlayerModel : IModel
|
|
||||||
{
|
|
||||||
public BindableProperty<string> Name { get; } = new("Player");
|
|
||||||
public BindableProperty<int> Health { get; } = new(100);
|
|
||||||
public BindableProperty<int> Gold { get; } = new(0);
|
|
||||||
public BindableProperty<int> Level { get; } = new(1);
|
|
||||||
|
|
||||||
public void Init() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### GameArchitecture.cs
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.architecture;
|
|
||||||
using MyGame.Models;
|
|
||||||
|
|
||||||
namespace MyGame
|
|
||||||
{
|
|
||||||
public class GameArchitecture : Architecture
|
|
||||||
{
|
|
||||||
public static IArchitecture Interface { get; private set; }
|
|
||||||
|
|
||||||
protected override void Init()
|
|
||||||
{
|
|
||||||
Interface = this;
|
|
||||||
RegisterModel(new PlayerModel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### GameController.cs
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using GFramework.Core.Abstractions.architecture;
|
|
||||||
using GFramework.Core.Abstractions.controller;
|
|
||||||
using GFramework.Core.extensions;
|
|
||||||
using MyGame.Models;
|
|
||||||
|
|
||||||
namespace MyGame.Controllers
|
|
||||||
{
|
|
||||||
public class GameController : IController
|
|
||||||
{
|
|
||||||
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
|
|
||||||
|
|
||||||
public void InitializePlayer()
|
|
||||||
{
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
playerModel.Name.Value = "勇者";
|
|
||||||
playerModel.Health.Value = 100;
|
|
||||||
playerModel.Gold.Value = 50;
|
|
||||||
playerModel.Level.Value = 1;
|
|
||||||
|
|
||||||
playerModel.Health.RegisterOnValueChanged(health =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"玩家生命值变化: {health}");
|
|
||||||
if (health <= 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("玩家死亡!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TakeDamage(int damage)
|
|
||||||
{
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
playerModel.Health.Value -= damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddGold(int amount)
|
|
||||||
{
|
|
||||||
var playerModel = this.GetModel<PlayerModel>();
|
|
||||||
playerModel.Gold.Value += amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Program.cs
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using MyGame;
|
|
||||||
using MyGame.Controllers;
|
|
||||||
|
|
||||||
var architecture = new GameArchitecture();
|
|
||||||
architecture.Initialize();
|
|
||||||
await architecture.WaitUntilReadyAsync();
|
|
||||||
|
|
||||||
var gameController = new GameController();
|
|
||||||
gameController.InitializePlayer();
|
|
||||||
gameController.TakeDamage(20);
|
|
||||||
gameController.AddGold(100);
|
|
||||||
```
|
|
||||||
|
|
||||||
## 运行结果
|
|
||||||
|
|
||||||
运行程序后,你将看到以下输出:
|
|
||||||
|
|
||||||
```
|
|
||||||
玩家生命值变化: 100
|
|
||||||
玩家生命值变化: 80
|
|
||||||
```
|
|
||||||
|
|
||||||
**验证步骤**:
|
|
||||||
1. 程序成功启动,没有异常
|
|
||||||
2. 控制台输出生命值变化信息
|
|
||||||
3. 玩家数据正确更新
|
|
||||||
|
|
||||||
## 下一步
|
|
||||||
|
|
||||||
恭喜!你已经学会了如何创建和使用 Model。接下来可以学习:
|
|
||||||
|
|
||||||
- [创建第一个 System](/zh-CN/tutorials/create-first-system) - 学习如何创建业务逻辑层
|
|
||||||
- [使用命令系统](/zh-CN/tutorials/use-command-system) - 学习如何封装操作
|
|
||||||
- [使用事件系统](/zh-CN/tutorials/use-event-system) - 学习组件间通信
|
|
||||||
|
|
||||||
## 相关文档
|
|
||||||
|
|
||||||
- [Model 层](/zh-CN/core/model) - Model 详细说明
|
|
||||||
- [属性系统](/zh-CN/core/property) - 可绑定属性详解
|
|
||||||
- [架构组件](/zh-CN/core/architecture) - 架构基础
|
|
||||||
- [Controller 层](/zh-CN/core/controller) - Controller 详细说明
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
---
|
|
||||||
title: {{TUTORIAL_TITLE}}
|
|
||||||
description: {{TUTORIAL_DESCRIPTION}}
|
|
||||||
---
|
|
||||||
|
|
||||||
# {{TUTORIAL_TITLE}}
|
|
||||||
|
|
||||||
## 学习目标
|
|
||||||
|
|
||||||
{{LEARNING_OBJECTIVES}}
|
|
||||||
|
|
||||||
## 前置条件
|
|
||||||
|
|
||||||
{{PREREQUISITES}}
|
|
||||||
|
|
||||||
## 步骤 1:{{STEP_1_TITLE}}
|
|
||||||
|
|
||||||
{{STEP_1_CONTENT}}
|
|
||||||
|
|
||||||
## 步骤 2:{{STEP_2_TITLE}}
|
|
||||||
|
|
||||||
{{STEP_2_CONTENT}}
|
|
||||||
|
|
||||||
## 步骤 3:{{STEP_3_TITLE}}
|
|
||||||
|
|
||||||
{{STEP_3_CONTENT}}
|
|
||||||
|
|
||||||
## 完整代码
|
|
||||||
|
|
||||||
{{FULL_CODE}}
|
|
||||||
|
|
||||||
## 运行结果
|
|
||||||
|
|
||||||
{{EXPECTED_OUTPUT}}
|
|
||||||
|
|
||||||
## 下一步
|
|
||||||
|
|
||||||
{{NEXT_STEPS}}
|
|
||||||
|
|
||||||
## 相关文档
|
|
||||||
|
|
||||||
{{RELATED_DOCS}}
|
|
||||||
@ -1,297 +0,0 @@
|
|||||||
# VitePress 文档验证
|
|
||||||
|
|
||||||
验证 VitePress 文档的质量和规范性,确保文档符合项目标准。
|
|
||||||
|
|
||||||
## 用途
|
|
||||||
|
|
||||||
此 skill 用于验证 Markdown 文档的格式和内容,包括:
|
|
||||||
- Frontmatter 格式正确性
|
|
||||||
- 内部链接有效性
|
|
||||||
- 代码块语法标记
|
|
||||||
- 标题层级结构
|
|
||||||
- 中文标点符号规范
|
|
||||||
- 泛型符号转义
|
|
||||||
|
|
||||||
## 调用方式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 验证单个文件
|
|
||||||
/vitepress-validate <文件路径>
|
|
||||||
|
|
||||||
# 验证整个目录
|
|
||||||
/vitepress-validate <目录路径>
|
|
||||||
|
|
||||||
# 验证所有文档
|
|
||||||
/vitepress-validate docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```bash
|
|
||||||
/vitepress-validate docs/zh-CN/api-reference/core/architecture.md
|
|
||||||
/vitepress-validate docs/zh-CN/core/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 验证项
|
|
||||||
|
|
||||||
### 1. Frontmatter 验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- YAML 语法正确性
|
|
||||||
- 必需字段存在(`title`、`description`)
|
|
||||||
- 字段值类型正确
|
|
||||||
- `outline` 字段值有效(`deep`、`[2,3]` 等)
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: Architecture # 必需
|
|
||||||
description: 架构基类说明 # 必需
|
|
||||||
outline: deep # 可选,但值必须有效
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 内部链接验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- 相对路径链接指向的文件存在
|
|
||||||
- 绝对路径链接格式正确
|
|
||||||
- 锚点链接对应的标题存在
|
|
||||||
- 没有损坏的链接
|
|
||||||
|
|
||||||
**有效链接格式**:
|
|
||||||
- `[文本](./file.md)` - 相对路径
|
|
||||||
- `[文本](/zh-CN/core/architecture)` - 绝对路径
|
|
||||||
- `[文本](#标题)` - 锚点链接
|
|
||||||
- `[文本](./file.md#标题)` - 组合链接
|
|
||||||
|
|
||||||
### 3. 代码块验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- 代码块有语法标记(```csharp、```bash 等)
|
|
||||||
- C# 代码块使用 `csharp` 标记(不是 `cs` 或 `c#`)
|
|
||||||
- 代码块正确闭合
|
|
||||||
- 没有未闭合的反引号
|
|
||||||
|
|
||||||
**正确格式**:
|
|
||||||
```markdown
|
|
||||||
\`\`\`csharp
|
|
||||||
public class Example { }
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
**错误格式**:
|
|
||||||
```markdown
|
|
||||||
\`\`\`cs // 应该使用 csharp
|
|
||||||
public class Example { }
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 标题层级验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- 标题层级不跳级(不能从 `#` 直接跳到 `###`)
|
|
||||||
- 每个文档只有一个一级标题(`#`)
|
|
||||||
- 标题层级递增合理
|
|
||||||
|
|
||||||
**正确示例**:
|
|
||||||
```markdown
|
|
||||||
# 一级标题
|
|
||||||
## 二级标题
|
|
||||||
### 三级标题
|
|
||||||
## 另一个二级标题
|
|
||||||
```
|
|
||||||
|
|
||||||
**错误示例**:
|
|
||||||
```markdown
|
|
||||||
# 一级标题
|
|
||||||
### 三级标题 ❌ 跳过了二级标题
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 中文标点符号验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- 中文句子使用全角标点(,。!?)
|
|
||||||
- 英文句子使用半角标点(,.!?)
|
|
||||||
- 代码和技术术语周围使用半角符号
|
|
||||||
- 括号使用规范
|
|
||||||
|
|
||||||
**规范示例**:
|
|
||||||
- "这是一个示例。" ✓(中文全角句号)
|
|
||||||
- "This is an example." ✓(英文半角句号)
|
|
||||||
- "`Architecture` 类提供了..." ✓(代码周围半角)
|
|
||||||
|
|
||||||
### 6. 泛型符号验证
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- 泛型符号正确转义(`<T>` → `<T>`)
|
|
||||||
- 仅在代码块外转义
|
|
||||||
- 代码块内保持原样
|
|
||||||
|
|
||||||
**正确示例**:
|
|
||||||
```markdown
|
|
||||||
`List<T>` 是一个泛型类。
|
|
||||||
|
|
||||||
\`\`\`csharp
|
|
||||||
List<T> items = new List<T>(); // 代码块内不转义
|
|
||||||
\`\`\`
|
|
||||||
```
|
|
||||||
|
|
||||||
## 验证脚本
|
|
||||||
|
|
||||||
### validate-frontmatter.sh
|
|
||||||
|
|
||||||
验证 Frontmatter 格式。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/vitepress-validate/scripts/validate-frontmatter.sh <文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
### validate-links.sh
|
|
||||||
|
|
||||||
验证内部链接有效性。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/vitepress-validate/scripts/validate-links.sh <文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
### validate-code-blocks.sh
|
|
||||||
|
|
||||||
验证代码块语法。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/vitepress-validate/scripts/validate-code-blocks.sh <文件路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
### validate-all.sh
|
|
||||||
|
|
||||||
执行所有验证。
|
|
||||||
|
|
||||||
**用法**:
|
|
||||||
```bash
|
|
||||||
.claude/skills/vitepress-validate/scripts/validate-all.sh <文件或目录路径>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 输出格式
|
|
||||||
|
|
||||||
### 验证通过
|
|
||||||
|
|
||||||
```
|
|
||||||
✓ docs/zh-CN/core/architecture.md
|
|
||||||
- Frontmatter: 通过
|
|
||||||
- 内部链接: 通过
|
|
||||||
- 代码块: 通过
|
|
||||||
- 标题层级: 通过
|
|
||||||
- 标点符号: 通过
|
|
||||||
- 泛型符号: 通过
|
|
||||||
```
|
|
||||||
|
|
||||||
### 验证失败
|
|
||||||
|
|
||||||
```
|
|
||||||
✗ docs/zh-CN/core/architecture.md
|
|
||||||
- Frontmatter: 失败
|
|
||||||
× 缺少必需字段: description
|
|
||||||
- 内部链接: 失败
|
|
||||||
× 损坏的链接: ./missing-file.md (第 45 行)
|
|
||||||
- 代码块: 警告
|
|
||||||
⚠ 使用了 'cs' 标记,建议使用 'csharp' (第 78 行)
|
|
||||||
- 标题层级: 通过
|
|
||||||
- 标点符号: 警告
|
|
||||||
⚠ 中文句子使用了半角句号 (第 102 行)
|
|
||||||
- 泛型符号: 失败
|
|
||||||
× 未转义的泛型符号: List<T> (第 120 行)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 修复建议
|
|
||||||
|
|
||||||
验证失败时,skill 会提供具体的修复建议:
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```
|
|
||||||
修复建议:
|
|
||||||
1. 在 Frontmatter 中添加 description 字段
|
|
||||||
2. 修复或删除损坏的链接: ./missing-file.md
|
|
||||||
3. 将代码块标记从 'cs' 改为 'csharp'
|
|
||||||
4. 将第 102 行的半角句号改为全角句号
|
|
||||||
5. 将第 120 行的 List<T> 改为 List<T>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置选项
|
|
||||||
|
|
||||||
### 严格模式
|
|
||||||
|
|
||||||
启用严格模式时,警告也会导致验证失败。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/vitepress-validate --strict docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 忽略特定检查
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 忽略标点符号检查
|
|
||||||
/vitepress-validate --ignore-punctuation docs/zh-CN/
|
|
||||||
|
|
||||||
# 忽略多个检查
|
|
||||||
/vitepress-validate --ignore-punctuation --ignore-generics docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 集成到工作流
|
|
||||||
|
|
||||||
### 生成后自动验证
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 生成 API 文档
|
|
||||||
/vitepress-api-doc GFramework.Core/architecture/Architecture.cs
|
|
||||||
|
|
||||||
# 2. 自动验证生成的文档
|
|
||||||
/vitepress-validate docs/zh-CN/api-reference/core/architecture.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### 批量验证
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 验证所有 API 文档
|
|
||||||
/vitepress-validate docs/zh-CN/api-reference/
|
|
||||||
|
|
||||||
# 验证所有文档
|
|
||||||
/vitepress-validate docs/zh-CN/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 退出代码
|
|
||||||
|
|
||||||
- `0` - 所有验证通过
|
|
||||||
- `1` - 存在错误
|
|
||||||
- `2` - 仅存在警告(非严格模式下仍返回 0)
|
|
||||||
|
|
||||||
## 相关 Skills
|
|
||||||
|
|
||||||
- `/vitepress-api-doc` - 生成 API 文档后自动验证
|
|
||||||
- `/vitepress-guide` - 生成指南文档后自动验证
|
|
||||||
- `/vitepress-tutorial` - 生成教程文档后自动验证
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **生成后立即验证**:每次生成文档后立即运行验证
|
|
||||||
2. **定期批量验证**:定期验证所有文档,确保一致性
|
|
||||||
3. **修复所有错误**:不要忽略验证错误,及时修复
|
|
||||||
4. **关注警告**:警告虽不致命,但应该重视并修复
|
|
||||||
5. **使用严格模式**:在 CI/CD 中使用严格模式确保质量
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 问题:误报泛型符号错误
|
|
||||||
**解决方案**:确保泛型符号在代码块外正确转义,代码块内保持原样
|
|
||||||
|
|
||||||
### 问题:中文标点符号检查过于严格
|
|
||||||
**解决方案**:使用 `--ignore-punctuation` 选项,或手动调整规则
|
|
||||||
|
|
||||||
### 问题:链接验证失败但文件确实存在
|
|
||||||
**解决方案**:检查文件路径大小写,确保路径完全匹配
|
|
||||||
|
|
||||||
## 版本历史
|
|
||||||
|
|
||||||
- v1.0.0 - 初始版本,支持 6 项基本验证
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 执行所有验证
|
|
||||||
# 用法: validate-all.sh <文件或目录路径>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TARGET="$1"
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
|
|
||||||
if [ -z "$TARGET" ]; then
|
|
||||||
echo "用法: $0 <文件或目录路径>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -e "$TARGET" ]; then
|
|
||||||
echo "错误: 路径不存在: $TARGET"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "VitePress 文档验证"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 收集所有 Markdown 文件
|
|
||||||
if [ -f "$TARGET" ]; then
|
|
||||||
FILES=("$TARGET")
|
|
||||||
elif [ -d "$TARGET" ]; then
|
|
||||||
mapfile -t FILES < <(find "$TARGET" -name "*.md" -type f)
|
|
||||||
else
|
|
||||||
echo "错误: 无效的路径: $TARGET"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ${#FILES[@]} -eq 0 ]; then
|
|
||||||
echo "未找到 Markdown 文件"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "找到 ${#FILES[@]} 个文件"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TOTAL_ERRORS=0
|
|
||||||
TOTAL_WARNINGS=0
|
|
||||||
PASSED_FILES=0
|
|
||||||
FAILED_FILES=0
|
|
||||||
|
|
||||||
for FILE in "${FILES[@]}"; do
|
|
||||||
echo "验证: $FILE"
|
|
||||||
echo "----------------------------------------"
|
|
||||||
|
|
||||||
FILE_ERRORS=0
|
|
||||||
FILE_WARNINGS=0
|
|
||||||
|
|
||||||
# 1. Frontmatter 验证
|
|
||||||
if bash "$SCRIPT_DIR/validate-frontmatter.sh" "$FILE" 2>&1 | grep -q "✗"; then
|
|
||||||
FILE_ERRORS=$((FILE_ERRORS + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. 链接验证
|
|
||||||
if bash "$SCRIPT_DIR/validate-links.sh" "$FILE" 2>&1 | grep -q "✗"; then
|
|
||||||
FILE_ERRORS=$((FILE_ERRORS + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 3. 代码块验证
|
|
||||||
OUTPUT=$(bash "$SCRIPT_DIR/validate-code-blocks.sh" "$FILE" 2>&1 || true)
|
|
||||||
if echo "$OUTPUT" | grep -q "✗"; then
|
|
||||||
FILE_ERRORS=$((FILE_ERRORS + 1))
|
|
||||||
fi
|
|
||||||
if echo "$OUTPUT" | grep -q "⚠"; then
|
|
||||||
FILE_WARNINGS=$((FILE_WARNINGS + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 统计结果
|
|
||||||
if [ $FILE_ERRORS -eq 0 ]; then
|
|
||||||
echo "✓ 验证通过"
|
|
||||||
PASSED_FILES=$((PASSED_FILES + 1))
|
|
||||||
else
|
|
||||||
echo "✗ 验证失败($FILE_ERRORS 个错误)"
|
|
||||||
FAILED_FILES=$((FAILED_FILES + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $FILE_WARNINGS -gt 0 ]; then
|
|
||||||
echo "⚠ $FILE_WARNINGS 个警告"
|
|
||||||
fi
|
|
||||||
|
|
||||||
TOTAL_ERRORS=$((TOTAL_ERRORS + FILE_ERRORS))
|
|
||||||
TOTAL_WARNINGS=$((TOTAL_WARNINGS + FILE_WARNINGS))
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "验证摘要"
|
|
||||||
echo "=========================================="
|
|
||||||
echo "总文件数: ${#FILES[@]}"
|
|
||||||
echo "通过: $PASSED_FILES"
|
|
||||||
echo "失败: $FAILED_FILES"
|
|
||||||
echo "总错误数: $TOTAL_ERRORS"
|
|
||||||
echo "总警告数: $TOTAL_WARNINGS"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ $TOTAL_ERRORS -eq 0 ]; then
|
|
||||||
echo "✓ 所有验证通过"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "✗ 验证失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 验证代码块语法
|
|
||||||
# 用法: validate-code-blocks.sh <文件路径>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
FILE="$1"
|
|
||||||
|
|
||||||
if [ -z "$FILE" ]; then
|
|
||||||
echo "用法: $0 <文件路径>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$FILE" ]; then
|
|
||||||
echo "错误: 文件不存在: $FILE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "验证代码块语法: $FILE"
|
|
||||||
|
|
||||||
ERROR_COUNT=0
|
|
||||||
WARNING_COUNT=0
|
|
||||||
|
|
||||||
# 检查未闭合的代码块
|
|
||||||
OPEN_COUNT=$(grep -c '^```' "$FILE" || true)
|
|
||||||
if [ $((OPEN_COUNT % 2)) -ne 0 ]; then
|
|
||||||
echo "✗ 错误: 存在未闭合的代码块"
|
|
||||||
ERROR_COUNT=$((ERROR_COUNT + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查 C# 代码块标记
|
|
||||||
LINE_NUM=0
|
|
||||||
while IFS= read -r LINE; do
|
|
||||||
LINE_NUM=$((LINE_NUM + 1))
|
|
||||||
|
|
||||||
# 检查是否使用了错误的 C# 标记
|
|
||||||
if echo "$LINE" | grep -qE '^```(cs|c#|C#)$'; then
|
|
||||||
echo "⚠ 警告: 第 $LINE_NUM 行使用了非标准标记,建议使用 'csharp'"
|
|
||||||
echo " 当前: $LINE"
|
|
||||||
WARNING_COUNT=$((WARNING_COUNT + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查代码块是否有语言标记
|
|
||||||
if echo "$LINE" | grep -qE '^```$'; then
|
|
||||||
# 检查下一行是否是代码(简单启发式:不是空行且不是 ```)
|
|
||||||
NEXT_LINE=$(sed -n "$((LINE_NUM + 1))p" "$FILE")
|
|
||||||
if [ -n "$NEXT_LINE" ] && ! echo "$NEXT_LINE" | grep -qE '^```'; then
|
|
||||||
echo "⚠ 警告: 第 $LINE_NUM 行的代码块缺少语言标记"
|
|
||||||
WARNING_COUNT=$((WARNING_COUNT + 1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done < "$FILE"
|
|
||||||
|
|
||||||
# 输出结果
|
|
||||||
if [ $ERROR_COUNT -eq 0 ] && [ $WARNING_COUNT -eq 0 ]; then
|
|
||||||
echo "✓ 代码块验证通过"
|
|
||||||
exit 0
|
|
||||||
elif [ $ERROR_COUNT -eq 0 ]; then
|
|
||||||
echo "⚠ 代码块验证通过(有 $WARNING_COUNT 个警告)"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "✗ 代码块验证失败($ERROR_COUNT 个错误,$WARNING_COUNT 个警告)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 验证 Frontmatter 格式
|
|
||||||
# 用法: validate-frontmatter.sh <文件路径>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
FILE="$1"
|
|
||||||
|
|
||||||
if [ -z "$FILE" ]; then
|
|
||||||
echo "用法: $0 <文件路径>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$FILE" ]; then
|
|
||||||
echo "错误: 文件不存在: $FILE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "验证 Frontmatter: $FILE"
|
|
||||||
|
|
||||||
# 检查是否有 Frontmatter(限制在前几行,避免匹配正文中的 '---')
|
|
||||||
if ! head -n 5 "$FILE" | grep -q "^---$"; then
|
|
||||||
echo "✗ 错误: 文件缺少 Frontmatter"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 提取 Frontmatter 内容(第一个 --- 到第二个 --- 之间)
|
|
||||||
FRONTMATTER=$(sed -n '/^---$/,/^---$/p' "$FILE" | sed '1d;$d')
|
|
||||||
|
|
||||||
if [ -z "$FRONTMATTER" ]; then
|
|
||||||
echo "✗ 错误: Frontmatter 为空"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查必需字段: title
|
|
||||||
if ! echo "$FRONTMATTER" | grep -q "^title:"; then
|
|
||||||
echo "✗ 错误: 缺少必需字段: title"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查必需字段: description
|
|
||||||
if ! echo "$FRONTMATTER" | grep -q "^description:"; then
|
|
||||||
echo "✗ 错误: 缺少必需字段: description"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查 outline 字段值(如果存在)
|
|
||||||
if echo "$FRONTMATTER" | grep -q "^outline:"; then
|
|
||||||
OUTLINE_VALUE=$(echo "$FRONTMATTER" | grep "^outline:" | sed 's/outline:\s*//')
|
|
||||||
if [ "$OUTLINE_VALUE" != "deep" ] && [ "$OUTLINE_VALUE" != "false" ] && ! echo "$OUTLINE_VALUE" | grep -qE '^\[.*\]$'; then
|
|
||||||
echo "⚠ 警告: outline 字段值可能无效: $OUTLINE_VALUE"
|
|
||||||
echo " 有效值: deep, false, [2,3]"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✓ Frontmatter 验证通过"
|
|
||||||
exit 0
|
|
||||||
@ -7,21 +7,19 @@
|
|||||||
|
|
||||||
## 当前恢复点
|
## 当前恢复点
|
||||||
|
|
||||||
- 恢复点编号:`DOCUMENTATION-GOVERNANCE-REFRESH-RP-007`
|
- 恢复点编号:`DOCUMENTATION-GOVERNANCE-REFRESH-RP-008`
|
||||||
- 当前阶段:`Phase 3`
|
- 当前阶段:`Phase 3`
|
||||||
- 当前焦点:
|
- 当前焦点:
|
||||||
- 已完成 `docs/zh-CN/core/events.md`、`property.md` 与 `logging.md` 的专题页重写
|
- 已建立统一公开 skill:`.agents/skills/gframework-doc-refresh/`
|
||||||
- 已按源码与测试复核 `docs/zh-CN/core/state-management.md`、`coroutine.md`,当前内容与实现基本一致,无需再做
|
- 文档重构入口已从“按 guide/tutorial/api 类型拆 skill”收口为“按源码模块驱动文档刷新”
|
||||||
机械改写
|
- 旧 `vitepress-*` skill 的模板、规范与校验逻辑已迁入新 skill 或 `_shared/`
|
||||||
- 已完成 `docs/zh-CN/game/scene.md` 与 `ui.md` 的专题页重写,当前内容已回到“项目自接 factory/root + router 基类”的真实边界
|
- 下一轮需要用统一 skill 推进 Godot 相关生成器页面核对
|
||||||
- 已完成 `docs/zh-CN/source-generators/context-aware-generator.md` 与 `priority-generator.md` 的专题页重写,当前内容已回到“真实生成成员、推荐 API 与兼容边界”的结构
|
|
||||||
- 下一轮需要把重心转到 Godot 相关生成器页面核对
|
|
||||||
|
|
||||||
## 当前状态摘要
|
## 当前状态摘要
|
||||||
|
|
||||||
- 文档治理规则已收口到仓库规范,README、站点入口与采用链路不再依赖旧文档自证
|
- 文档治理规则已收口到仓库规范,README、站点入口与采用链路不再依赖旧文档自证
|
||||||
- 高优先级模块入口与 `core` 关键专题页已回到可作为默认导航入口的状态,本轮计划中的 `core` 剩余高风险页面已完成收口
|
- 高优先级模块入口与 `core` 关键专题页已回到可作为默认导航入口的状态,本轮计划中的 `core` 剩余高风险页面已完成收口
|
||||||
- 当前主题仍是 active topic,因为 `source-generators` 栏目下的 Godot 相关页面仍可能包含与实现漂移的旧内容
|
- 当前主题仍是 active topic,因为 `source-generators` 栏目下的 Godot 相关页面仍可能包含与实现漂移的旧内容,且统一 skill 还需要在该场景上继续落地使用
|
||||||
|
|
||||||
## 当前活跃事实
|
## 当前活跃事实
|
||||||
|
|
||||||
@ -51,6 +49,11 @@
|
|||||||
- `docs/zh-CN/source-generators/priority-generator.md` 已改成“生成 `IPrioritized`、priority-aware 检索 API、动态优先级边界与诊断”的结构,
|
- `docs/zh-CN/source-generators/priority-generator.md` 已改成“生成 `IPrioritized`、priority-aware 检索 API、动态优先级边界与诊断”的结构,
|
||||||
不再把 `GetAllByPriority<T>()` / `system.Init()` 当作所有场景的默认示例
|
不再把 `GetAllByPriority<T>()` / `system.Init()` 当作所有场景的默认示例
|
||||||
- 本轮重写后再次执行 `cd docs && bun run build` 通过,当前 `source-generators` 栏目改动没有破坏站点构建
|
- 本轮重写后再次执行 `cd docs && bun run build` 通过,当前 `source-generators` 栏目改动没有破坏站点构建
|
||||||
|
- `.agents/skills/gframework-doc-refresh/SKILL.md` 已改成标准 YAML frontmatter skill,并明确支持模块输入、证据顺序、输出优先级与验证步骤
|
||||||
|
- `.agents/skills/_shared/module-map.json` 已收口为源码模块映射表,覆盖源码目录、测试项目、README、`docs/zh-CN` 栏目与 `ai-libs/` 参考入口
|
||||||
|
- 旧 `vitepress-api-doc`、`vitepress-batch-api`、`vitepress-doc-generator`、`vitepress-guide`、`vitepress-tutorial`、`vitepress-validate`
|
||||||
|
已不再保留为可用公开 skill 定义文件
|
||||||
|
- `ai-libs/` 已纳入统一 skill 的标准证据链,只作为消费者接入参考,不再替代源码与测试契约
|
||||||
|
|
||||||
## 当前风险
|
## 当前风险
|
||||||
|
|
||||||
@ -59,6 +62,14 @@
|
|||||||
继续按源码、测试、`*.csproj` 与 `ai-libs/` 下已验证参考实现核对剩余 Godot 相关页面,不把旧文档当事实来源
|
继续按源码、测试、`*.csproj` 与 `ai-libs/` 下已验证参考实现核对剩余 Godot 相关页面,不把旧文档当事实来源
|
||||||
- 采用路径误导风险:根聚合包与模块边界若再次被写错,会继续误导消费者的包选择
|
- 采用路径误导风险:根聚合包与模块边界若再次被写错,会继续误导消费者的包选择
|
||||||
- 缓解措施:保持“源码与包关系优先”的证据顺序,改动采用说明时同步核对包依赖与生成器 wiring
|
- 缓解措施:保持“源码与包关系优先”的证据顺序,改动采用说明时同步核对包依赖与生成器 wiring
|
||||||
|
- 模块映射不全风险:统一 skill 若遗漏模块别名、测试项目或 docs 栏目映射,会让后续扫描阶段直接失焦
|
||||||
|
- 缓解措施:以当前 `*.csproj` 族为 canonical module list,统一维护 `.agents/skills/_shared/module-map.json`
|
||||||
|
- `ai-libs/` 漂移风险:参考项目若滞后于当前实现,可能把过时 wiring 重新带回文档
|
||||||
|
- 缓解措施:在 skill 中固定“源码/测试优先,`ai-libs/` 只补 adoption path”的证据顺序
|
||||||
|
- 旧模板迁移失真风险:旧 `vitepress-*` skill 的模板和规范若原样沿用,可能继续输出过时结构
|
||||||
|
- 缓解措施:只迁移可复用骨架,把输出优先级和证据规则重写进统一 skill
|
||||||
|
- 统一入口过宽风险:若 `gframework-doc-refresh` 的触发描述过宽,可能在模块不明确时误进入文档生成
|
||||||
|
- 缓解措施:要求先做模块归一化;遇到栏目别名歧义时只返回建议,不直接生成文档
|
||||||
- Active 入口回膨胀风险:后续若把栏目级重写过程直接追加到 active 文档,会再次拖慢恢复
|
- Active 入口回膨胀风险:后续若把栏目级重写过程直接追加到 active 文档,会再次拖慢恢复
|
||||||
- 缓解措施:阶段完成并验证后,继续把细节迁入本 topic 的 `archive/`
|
- 缓解措施:阶段完成并验证后,继续把细节迁入本 topic 的 `archive/`
|
||||||
- review 跟进遗漏风险:如果 PR review 抓取继续优先选中空 review body,会漏掉 CodeRabbit 的 Nitpick 和
|
- review 跟进遗漏风险:如果 PR review 抓取继续优先选中空 review body,会漏掉 CodeRabbit 的 Nitpick 和
|
||||||
@ -76,10 +87,13 @@
|
|||||||
- active 跟踪文件已按 `ai-plan` 治理规则精简为当前恢复入口
|
- active 跟踪文件已按 `ai-plan` 治理规则精简为当前恢复入口
|
||||||
- `cd docs && bun run build`
|
- `cd docs && bun run build`
|
||||||
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json`
|
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json`
|
||||||
|
- `python3 .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Core`
|
||||||
|
- `python3 .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Godot.SourceGenerators`
|
||||||
|
- `python3 .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Cqrs`
|
||||||
|
|
||||||
## 下一步
|
## 下一步
|
||||||
|
|
||||||
1. 继续核对 Godot 相关生成器页面,优先处理 `godot-project-generator.md`、`get-node-generator.md` 与
|
1. 继续核对 Godot 相关生成器页面,优先处理 `godot-project-generator.md`、`get-node-generator.md` 与
|
||||||
`bind-node-signal-generator.md`
|
`bind-node-signal-generator.md`,优先用 `gframework-doc-refresh` 的模块扫描结果驱动判断
|
||||||
2. 重点确认 `project.godot`、`AutoLoad` / `InputActions`、`GetNode` / `BindNodeSignal` 示例仍与当前包关系和生成器入口一致
|
2. 重点确认 `project.godot`、`AutoLoad` / `InputActions`、`GetNode` / `BindNodeSignal` 示例仍与当前包关系和生成器入口一致
|
||||||
3. 若 active trace 再积累新的已完成阶段,按恢复点粒度迁入 `archive/traces/`,避免默认启动入口再次膨胀
|
3. 若 active trace 再积累新的已完成阶段,按恢复点粒度迁入 `archive/traces/`,避免默认启动入口再次膨胀
|
||||||
|
|||||||
@ -181,3 +181,57 @@
|
|||||||
`bind-node-signal-generator.md`
|
`bind-node-signal-generator.md`
|
||||||
2. 重点确认 `project.godot`、`AutoLoad` / `InputActions`、`GetNode` / `BindNodeSignal` 示例仍与当前包关系和生成器入口一致
|
2. 重点确认 `project.godot`、`AutoLoad` / `InputActions`、`GetNode` / `BindNodeSignal` 示例仍与当前包关系和生成器入口一致
|
||||||
3. 若 Godot 页面也出现连续收口结果,再按恢复点粒度整理 active trace,避免默认入口继续膨胀
|
3. 若 Godot 页面也出现连续收口结果,再按恢复点粒度整理 active trace,避免默认入口继续膨胀
|
||||||
|
|
||||||
|
## 2026-04-22
|
||||||
|
|
||||||
|
### 阶段:统一文档编排 skill 收口(RP-008)
|
||||||
|
|
||||||
|
- 依据当前主题“文档治理 + 持续刷新”的目标,复核 `.agents/skills/` 后确认:现有 `vitepress-api-doc`、
|
||||||
|
`vitepress-batch-api`、`vitepress-doc-generator`、`vitepress-guide`、`vitepress-tutorial` 与
|
||||||
|
`vitepress-validate` 仍保留旧的并列入口模型,其中多数 `SKILL.md` 没有标准 YAML frontmatter,已经不适合作为当前
|
||||||
|
Codex skill 继续公开暴露
|
||||||
|
- 结合当前 `*.csproj`、`docs/zh-CN` 栏目、模块 README 与 `ai-libs/CoreGrid` 参考入口,建立
|
||||||
|
`.agents/skills/_shared/module-map.json`,把文档刷新主输入固定为真实源码模块,而不是 `guide/tutorial/api`
|
||||||
|
之类的文档类型
|
||||||
|
- 重写 `.agents/skills/_shared/DOCUMENTATION_STANDARDS.md`,去掉已经失真的固定页面清单,明确固定证据顺序:
|
||||||
|
1. 源码 / XML docs / `*.csproj`
|
||||||
|
2. 测试与 snapshot
|
||||||
|
3. README
|
||||||
|
4. 当前 `docs/zh-CN`
|
||||||
|
5. `ai-libs/`
|
||||||
|
6. 归档文档
|
||||||
|
- 新增 `.agents/skills/gframework-doc-refresh/`,补齐:
|
||||||
|
- 标准 frontmatter 的 `SKILL.md`
|
||||||
|
- `agents/openai.yaml`
|
||||||
|
- `references/` 下的模块选择、证据顺序与输出策略说明
|
||||||
|
- `templates/` 下的 landing/topic/API/tutorial 骨架
|
||||||
|
- `scripts/scan_module_evidence.py`
|
||||||
|
- 迁移后的文档校验脚本 `validate-*.sh`
|
||||||
|
- `scan_module_evidence.py` 已支持:
|
||||||
|
- 模块名与别名归一化
|
||||||
|
- docs 栏目别名歧义检测
|
||||||
|
- 输出源码、测试、README、docs、`ai-libs/` 的存在性扫描结果
|
||||||
|
- 对 landing/topic/fallback 状态做基础判断,作为后续页面收口入口
|
||||||
|
- `.agents/skills/README.md` 已改成“统一公开入口 + 共享资源”说明,不再把旧 `vitepress-*` skill 当成推荐工作流
|
||||||
|
- 旧 `vitepress-*` skill 文件已删除;目录本身在当前 Windows-backed worktree 上因只读元数据仍可能残留为空目录,但由于
|
||||||
|
`SKILL.md` 已删除,它们不再构成可发现的 skill 入口
|
||||||
|
|
||||||
|
### 验证(RP-008)
|
||||||
|
|
||||||
|
- `python3 -B .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Core`
|
||||||
|
- `python3 -B .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Godot.SourceGenerators`
|
||||||
|
- `python3 -B .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py Cqrs`
|
||||||
|
- `python3 -B .agents/skills/gframework-doc-refresh/scripts/scan_module_evidence.py source-generators --json`
|
||||||
|
|
||||||
|
### 当前结论(RP-008)
|
||||||
|
|
||||||
|
- 当前文档刷新入口已经从“按文档类型拆 skill”转为“按源码模块驱动文档评估与更新”
|
||||||
|
- `ai-libs/` 已正式纳入标准证据链,但仅用于 adoption path 和真实 wiring 参考,不覆盖源码契约
|
||||||
|
- 旧 skill 中仍有价值的模板与校验逻辑已经迁入统一入口或 `_shared/`,后续不需要再维护多套并列说明
|
||||||
|
|
||||||
|
### 下一步(RP-008)
|
||||||
|
|
||||||
|
1. 使用 `gframework-doc-refresh` 对 `Godot.SourceGenerators` 做一次真实模块扫描,并据此继续刷新
|
||||||
|
`godot-project-generator.md`、`get-node-generator.md` 与 `bind-node-signal-generator.md`
|
||||||
|
2. 若发现 `module-map.json` 在 Godot 场景下仍缺少别名或 docs 映射,再回补共享映射,而不是在单页文档里硬编码
|
||||||
|
3. 若后续 skill 收口过程继续积累细节,再把迁移细节归档到本 topic 的 `archive/`,保持 active trace 可快速恢复
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user