fix(docs): 修复文档中代码块转义问题并更新插件配置

- 将 markdownEscapePlugin 重命名为 safeGenericEscapePlugin
- 更新插件逻辑以保护 HTML 标签并仅转义泛型形式的尖括号
- 修复文档中所有代码块的语法标记为正确的 csharp 格式
- 更新依赖缓存文件的哈希值
- 修正事件文档中泛型类型的显示格式
This commit is contained in:
GeWuYou 2026-02-11 15:15:28 +08:00
parent 6cc0ddf7f9
commit 7dd9b99e49
8 changed files with 116 additions and 101 deletions

View File

@ -1,25 +1,25 @@
{
"hash": "6e3217ee",
"configHash": "ff691e50",
"hash": "2500e5b1",
"configHash": "3af8c6da",
"lockfileHash": "42b6a898",
"browserHash": "d5f41485",
"browserHash": "36f3405c",
"optimized": {
"vue": {
"src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "ed53cbd8",
"fileHash": "d870a771",
"needsInterop": false
},
"vitepress > @vue/devtools-api": {
"src": "../../../node_modules/@vue/devtools-api/dist/index.js",
"file": "vitepress___@vue_devtools-api.js",
"fileHash": "e7446b18",
"fileHash": "d4c69f44",
"needsInterop": false
},
"vitepress > @vueuse/core": {
"src": "../../../node_modules/@vueuse/core/dist/index.js",
"file": "vitepress___@vueuse_core.js",
"fileHash": "6dc472ff",
"fileHash": "05ae35d2",
"needsInterop": false
}
},

View File

@ -8,7 +8,7 @@ export default defineConfig({
/** GitHub Pages / 子路径部署 */
base: '/GFramework/',
vite: {
plugins: [markdownEscapePlugin()]
plugins: [safeGenericEscapePlugin()]
},
/** 多语言 */
locales: {
@ -172,33 +172,48 @@ export default defineConfig({
})
import { defineConfig } from 'vitepress'
function markdownEscapePlugin() {
function safeGenericEscapePlugin() {
return {
name: 'markdown-escape-plugin',
enforce: 'pre', // 在 vitepress 之前执行
name: 'safe-generic-escape',
enforce: 'pre',
transform(code: string, id: string) {
if (!id.endsWith('.md')) return
const codeBlocks: string[] = []
const htmlBlocks: string[] = []
// 1替换代码块
const replaced = code.replace(/```[\s\S]*?```/g, (match) => {
const index = codeBlocks.length
// 1保护代码块 ``` ```
let processed = code.replace(/```[\s\S]*?```/g, (match) => {
const i = codeBlocks.length
codeBlocks.push(match)
return `__CODE_BLOCK_${index}__`
return `__CODE_BLOCK_${i}__`
})
// 2⃣ 转义普通文本中的 < >
let escaped = replaced
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
// 3⃣ 恢复代码块
codeBlocks.forEach((block, index) => {
escaped = escaped.replace(`__CODE_BLOCK_${index}__`, block)
// 2⃣ 保护 HTML 标签(避免破坏 Vue SFC
processed = processed.replace(/<\/?[a-zA-Z][^>]*>/g, (match) => {
const i = htmlBlocks.length
htmlBlocks.push(match)
return `__HTML_BLOCK_${i}__`
})
return escaped
// 3⃣ 只转义“泛型形式”的 <T> 或 <K, V>
processed = processed.replace(
/<([A-Z][A-Za-z0-9_,\s]*)>/g,
(_, inner) => `&lt;${inner}&gt;`
)
// 4⃣ 恢复 HTML
htmlBlocks.forEach((block, i) => {
processed = processed.replace(`__HTML_BLOCK_${i}__`, block)
})
// 5⃣ 恢复代码块
codeBlocks.forEach((block, i) => {
processed = processed.replace(`__CODE_BLOCK_${i}__`, block)
})
return processed
}
}
}

View File

@ -73,7 +73,7 @@ onClicked.Trigger();
unregister.UnRegister();
```
### 2. [Event<T>](EasyEvent.cs)
### 2. [Event`<T>`](EasyEvent.cs)
单参数泛型事件类,支持一个参数的事件。
@ -99,7 +99,7 @@ onScoreChanged.Trigger(100);
**使用示例:**
```
```csharp
// 伤害事件:攻击者、伤害值
var onDamageDealt = new Event<string, int>();
@ -117,7 +117,7 @@ onDamageDealt.Trigger("Player", 50);
**使用示例:**
``csharp
```csharp
// 注册全局事件类型
EasyEvents.Register<GameStartEvent>();
@ -140,7 +140,7 @@ gameStartEvent.Trigger();
**使用示例:**
``csharp
```csharp
// 使用全局事件系统
var eventBus = new EventBus();
@ -166,7 +166,7 @@ eventBus.Send<PlayerDiedEvent>();
**使用示例:**
``csharp
```csharp
Action onUnregister = () => GD.Print("Unregistered");
var unregister = new DefaultUnRegister(onUnregister);
@ -180,7 +180,7 @@ unregister.UnRegister();
**使用示例:**
``csharp
```csharp
var onAnyInput = new OrEvent()
.Or(onKeyPressed)
.Or(onMouseClicked)
@ -199,7 +199,7 @@ onAnyInput.Register(() =>
**使用示例:**
``csharp
```csharp
var unregisterList = new UnRegisterList();
// 添加到列表
@ -224,7 +224,7 @@ unregisterList.UnRegisterAll();
### 定义事件类
``csharp
```csharp
// 简单事件
public struct GameStartedEvent { }
@ -247,7 +247,7 @@ public struct LevelCompletedEvent
### Model 中发送事件
``csharp
```csharp
public class PlayerModel : AbstractModel
{
public BindableProperty<int> Health { get; } = new(100);
@ -273,7 +273,7 @@ public class PlayerModel : AbstractModel
### System 中发送事件
``csharp
```csharp
public class CombatSystem : AbstractSystem
{
protected override void OnInit() { }
@ -295,7 +295,7 @@ public class CombatSystem : AbstractSystem
### Controller 中注册事件
``csharp
```csharp
public partial class GameController : Node, IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
@ -343,7 +343,7 @@ public partial class GameController : Node, IController
### 1. 事件链式组合
``csharp
```csharp
// 使用 Or 组合多个事件
var onAnyDamage = new OrEvent()
.Or(onPhysicalDamage)
@ -358,7 +358,7 @@ onAnyDamage.Register(() =>
### 2. 事件过滤
``csharp
```csharp
// 只处理高伤害事件
this.RegisterEvent<DamageDealtEvent>(e =>
{
@ -371,7 +371,7 @@ this.RegisterEvent<DamageDealtEvent>(e =>
### 3. 事件转发
``csharp
```csharp
public class EventBridge : AbstractSystem
{
protected override void OnInit()
@ -391,7 +391,7 @@ public class EventBridge : AbstractSystem
### 4. 临时事件监听
``csharp
```csharp
public class TutorialController : Node, IController
{
public override void _Ready()
@ -409,7 +409,7 @@ public class TutorialController : Node, IController
### 5. 条件事件
``csharp
```csharp
public class AchievementSystem : AbstractSystem
{
private int _killCount = 0;
@ -437,7 +437,7 @@ public class AchievementSystem : AbstractSystem
### 使用 UnRegisterList
``csharp
```csharp
public class MyController : Node, IController
{
// 统一管理所有注销对象
@ -463,7 +463,7 @@ public class MyController : Node, IController
### 使用 Godot 节点生命周期
``csharp
```csharp
public override void _Ready()
{
// 当节点退出场景树时自动注销

View File

@ -121,7 +121,7 @@ public GetItemCountQuery(string itemId) : base(new GetItemCountQueryInput(itemId
```
### 2. 发送查询(在 Controller 中)
### 2. 发送查询
```csharp
public partial class ShopUI : Control, IController
@ -156,7 +156,7 @@ public partial class ShopUI : Control, IController
### 3. 在 System 中使用
``csharp
```csharp
public class CombatSystem : AbstractSystem
{
protected override void OnInit()
@ -185,7 +185,7 @@ this.RegisterEvent<EnemyAttackEvent>(OnEnemyAttack);
### 1. 带参数的复杂查询
``csharp
```csharp
// 查询指定范围内的敌人列表
public class GetEnemiesInRangeQuery : AbstractQuery<List<Enemy>>
{
@ -209,7 +209,7 @@ var enemies = this.SendQuery(new GetEnemiesInRangeQuery
### 2. 组合查询
``csharp
```csharp
// 查询玩家是否可以使用技能
public class CanUseSkillQuery : AbstractQuery<bool>
{
@ -256,7 +256,7 @@ public string SkillId { get; set; }
### 3. 聚合数据查询
``csharp
```csharp
// 查询玩家战斗力
public class GetPlayerPowerQuery : AbstractQuery<int>
{
@ -295,7 +295,7 @@ public class GetPlayerInfoQuery : AbstractQuery<PlayerInfo>
### 4. 跨 System 查询
``csharp
```csharp
// 在 AI System 中查询玩家状态
public class EnemyAISystem : AbstractSystem
{
@ -346,7 +346,7 @@ protected override void OnInit() { }
- **返回值**:有返回值
- **示例**:获取金币数量、检查技能冷却、查询玩家位置
``csharp
```csharp
// ❌ 错误:在 Query 中修改状态
public class BadQuery : AbstractQuery<int>
{
@ -392,7 +392,7 @@ public class AddGoldCommand : AbstractCommand
### 1. 缓存查询结果
``csharp
```csharp
// 在 Model 中缓存复杂计算
public class PlayerModel : AbstractModel
{
@ -424,7 +424,7 @@ private int? _cachedPower;
### 2. 批量查询
``csharp
```csharp
// 一次查询多个数据,而不是多次单独查询
public class GetMultipleItemCountsQuery : AbstractQuery<Dictionary<string, int>>
{

View File

@ -77,7 +77,7 @@ IContextAware (上下文感知接口)
### 1. Component 继承 ContextAwareBase
``csharp
```csharp
// 组件通过继承 ContextAwareBase 获得架构上下文访问能力
public partial class PlayerController : Node, IController
{
@ -99,7 +99,7 @@ public partial class PlayerController : Node, IController
### 2. Command 继承 AbstractCommand (IContextAware)
``csharp
```csharp
// Command 继承 AbstractCommand自动成为 IContextAware
public class BuyItemCommand : AbstractCommand
{
@ -124,7 +124,7 @@ public class BuyItemCommand : AbstractCommand
### 3. 自定义组件遵循规则
``csharp
```csharp
// 自定义管理器遵循框架规则,继承 ContextAwareBase
public class SaveManager : ContextAwareBase
{
@ -151,7 +151,7 @@ public class SaveManager : ContextAwareBase
### 1. 组件注册规则
``csharp
```csharp
public class GameArchitecture : Architecture
{
protected override void Init()
@ -166,7 +166,7 @@ public class GameArchitecture : Architecture
### 2. Command/Query 自动注入规则
``csharp
```csharp
// Controller 中发送 Command
public class ShopUI : Control, IController
{
@ -200,7 +200,7 @@ public class BuyItemCommand : AbstractCommand
Rule 接口体现了依赖注入DI的思想
``csharp
```csharp
// 接口定义了"需要什么"
public interface IContextAware
{
@ -225,7 +225,7 @@ public static class CanSendExtensions
Rule 接口遵循接口隔离原则,每个接口职责单一:
``csharp
```csharp
// ❌ 不好的设计:一个大接口包含所有能力
public interface IBigInterface
{
@ -247,7 +247,7 @@ public interface ICanSendCommand { ... } // 只负责发送 Command
通过接口组合实现不同能力:
``csharp
```csharp
// Controller 需要获取 Model 和发送 Command
public interface IController : ICanGetModel, ICanGetSystem, ICanSendCommand,
ICanSendQuery, ICanRegisterEvent
@ -271,7 +271,7 @@ public interface ISystem : IContextAware, ICanGetModel, ICanGetUtility, ICanGetS
### 自定义规则接口
``csharp
```csharp
// 定义新的规则接口
public interface ICanAccessDatabase : IBelongToArchitecture
{

View File

@ -13,7 +13,7 @@ Utility 标记接口,所有工具类都应实现此接口。
**接口定义:**
``csharp
```csharp
public interface IUtility
{
// 标记接口,无方法定义
@ -26,7 +26,7 @@ public interface IUtility
**接口定义:**
``csharp
```csharp
public interface IContextUtility : IUtility
{
void Init(); // 初始化上下文工具
@ -139,7 +139,7 @@ public class TimeUtility : IUtility
### 2. 注册 Utility
``csharp
```csharp
public class GameArchitecture : Architecture
{
protected override void Init()
@ -154,7 +154,7 @@ public class GameArchitecture : Architecture
### 3. 使用 Utility
``csharp
```csharp
// 在 System 中使用
public class SaveSystem : AbstractSystem
{
@ -223,7 +223,7 @@ public class MovePlayerCommand : AbstractCommand
### 1. 序列化/反序列化工具
``csharp
```csharp
public class JsonUtility : IUtility
{
public string Serialize<T>(T obj)
@ -254,7 +254,7 @@ public class JsonUtility : IUtility
### 2. 随机数工具
``csharp
```csharp
public class RandomUtility : IUtility
{
private Random _random = new Random();
@ -294,7 +294,7 @@ public class RandomUtility : IUtility
### 3. 字符串工具
``csharp
```csharp
public class StringUtility : IUtility
{
public string Truncate(string text, int maxLength, string suffix = "...")
@ -327,7 +327,7 @@ public class StringUtility : IUtility
### 4. 加密工具
``csharp
```csharp
public class EncryptionUtility : IUtility
{
private const string EncryptionKey = "YourSecretKey123";
@ -367,7 +367,7 @@ public class EncryptionUtility : IUtility
### 5. 对象池工具
``csharp
```csharp
public class ObjectPoolUtility : IUtility
{
private Dictionary<Type, Queue<object>> _pools = new();
@ -410,7 +410,7 @@ public class ObjectPoolUtility : IUtility
### 6. 日志工具
``csharp
```csharp
public class LogUtility : IUtility
{
public enum LogLevel
@ -503,7 +503,7 @@ public class CombatSystem : AbstractSystem
## 错误示例
``csharp
```csharp
// ❌ 错误Utility 中存储状态
public class BadUtility : IUtility
{
@ -543,7 +543,7 @@ public class IdGeneratorSystem : AbstractSystem
### 1. 缓存计算结果
``csharp
```csharp
public class PathfindingUtility : IUtility
{
private Dictionary<(Vector3, Vector3), List<Vector3>> _pathCache = new();
@ -582,7 +582,7 @@ public class PathfindingUtility : IUtility
### 2. 对象复用
``csharp
```csharp
public class CollectionUtility : IUtility
{
private List<Vector3> _tempList = new();

View File

@ -95,7 +95,7 @@ public class PlayerModel : AbstractModel
应用的业务逻辑处理层。
``csharp
```csharp
public class CombatSystem : AbstractSystem
{
protected override void OnInit()
@ -136,7 +136,7 @@ this.GetEvent<AttackEvent>().Register(OnAttack);
连接 UI 和业务逻辑的桥梁。
``csharp
```csharp
public class PlayerController : IController
{
private IArchitecture _architecture;
@ -176,7 +176,7 @@ public class PlayerController : IController
提供无状态的辅助功能。
``csharp
```csharp
public class StorageUtility : IUtility
{
public void SaveData<T>(string key, T data)
@ -205,7 +205,7 @@ public class StorageUtility : IUtility
用于修改应用状态的操作:
``csharp
```csharp
public class MovePlayerCommand : AbstractCommand
{
public Vector2 Direction { get; set; }
@ -222,7 +222,7 @@ public class MovePlayerCommand : AbstractCommand
用于查询应用状态:`
``csharp
```csharp
public class GetPlayerHealthQuery : AbstractQuery<int>
{
protected override int OnDo()
@ -249,7 +249,7 @@ this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
### BindableProperty
``csharp
```csharp
public class PlayerModel : AbstractModel
{
public BindableProperty<int> Health { get; } = new(100);
@ -274,7 +274,7 @@ playerModel.Health.Register(newValue => {
### 1. 分层职责明确
``csharp
```csharp
// ✅ 正确Model 只存储数据
public class PlayerModel : AbstractModel
{
@ -293,7 +293,7 @@ public class PlayerModel : AbstractModel
### 2. 事件驱动设计
``csharp
```csharp
// ✅ 正确:使用事件解耦
public class CombatSystem : AbstractSystem
{
@ -317,7 +317,7 @@ public class CombatSystem : AbstractSystem
### 3. 命令查询分离
``csharp
```csharp
// ✅ 正确:明确区分命令和查询
public class MovePlayerCommand : AbstractCommand { } // 修改状态
public class GetPlayerPositionQuery : AbstractQuery<Vector2> { } // 查询状态

View File

@ -86,7 +86,7 @@ graph TD
#### 基本音频设置
``csharp
```csharp
// 创建音频配置数据
var settings = new AudioSettings
{
@ -104,7 +104,7 @@ audioSettings.Apply();
#### 自定义音频总线映射
``csharp
```csharp
// 自定义音频总线映射
var customBusMap = new AudioBusMap
{
@ -128,7 +128,7 @@ await audioSettings.Apply();
#### 通过设置系统使用
``csharp
```csharp
// 注册音频设置到设置模型
var settingsModel = this.GetModel<ISettingsModel>();
var audioSettingsData = settingsModel.Get<AudioSettings>();
@ -145,7 +145,7 @@ await godotAudioSettings.Apply();
#### 基本图形设置
``csharp
```csharp
// 创建图形设置
var graphicsSettings = new GodotGraphicsSettings
{
@ -160,7 +160,7 @@ await graphicsSettings.Apply();
#### 窗口模式切换
``csharp
```csharp
public class DisplayManager : Node
{
private GodotGraphicsSettings _graphicsSettings;
@ -188,7 +188,7 @@ public class DisplayManager : Node
#### 预设分辨率配置
``csharp
```csharp
public class ResolutionPresets
{
public static readonly (int width, int height)[] CommonResolutions =
@ -214,7 +214,7 @@ public class ResolutionPresets
### AudioBusMap
``csharp
```csharp
public sealed class AudioBusMap
{
public string Master { get; init; } = "Master";
@ -231,7 +231,7 @@ public sealed class AudioBusMap
### GodotAudioSettings
``csharp
```csharp
public class GodotAudioSettings(AudioSettings settings, AudioBusMap busMap) : IApplyAbleSettings
{
public Task Apply();
@ -245,7 +245,7 @@ public class GodotAudioSettings(AudioSettings settings, AudioBusMap busMap) : IA
**Apply 方法实现:**
``csharp
```csharp
public Task Apply()
{
SetBus(busMap.Master, settings.MasterVolume);
@ -257,7 +257,7 @@ public Task Apply()
### GodotGraphicsSettings
``csharp
```csharp
public class GodotGraphicsSettings : GraphicsSettings, IApplyAbleSettings
{
public Task Apply();
@ -277,7 +277,7 @@ public class GodotGraphicsSettings : GraphicsSettings, IApplyAbleSettings
Godot 音频系统使用分贝dB作为音量单位而我们通常使用线性值0-1
``csharp
```csharp
// 线性值到分贝转换
float linearVolume = 0.5f; // 50% 音量
float dbVolume = Mathf.LinearToDb(linearVolume); // 转换为分贝
@ -290,7 +290,7 @@ AudioServer.SetBusVolumeDb(busIndex, dbVolume);
为避免完全静音(-inf dB应用了最小音量限制
``csharp
```csharp
float clampedVolume = Mathf.Clamp(linear, 0.0001f, 1f);
float dbVolume = Mathf.LinearToDb(clampedVolume);
```
@ -299,7 +299,7 @@ float dbVolume = Mathf.LinearToDb(clampedVolume);
#### 全屏模式
``csharp
```csharp
// 设置全屏
DisplayServer.WindowSetMode(DisplayServer.WindowMode.ExclusiveFullscreen);
DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true);
@ -307,7 +307,7 @@ DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true);
#### 窗口化模式
``csharp
```csharp
// 设置窗口化
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
DisplayServer.WindowSetSize(newSize);
@ -325,7 +325,7 @@ DisplayServer.WindowSetPosition(position);
#### 音量变化平滑过渡
``csharp
```csharp
public class AudioManager : Node
{
private Tween _volumeTween;
@ -398,7 +398,7 @@ public class CustomAudioManager : Node
#### 音频设置验证
``csharp
```csharp
public static class AudioSettingsValidator
{
public static bool ValidateBusNames(AudioBusMap busMap)
@ -428,7 +428,7 @@ public static class AudioSettingsValidator
#### 分辨率变更安全检查
``csharp
```csharp
public static class DisplayValidator
{
public static bool IsResolutionSupported(int width, int height)
@ -451,7 +451,7 @@ public static class DisplayValidator
#### 图形设置持久化
``csharp
```csharp
public class GraphicsSettingsManager : Node
{
private const string SettingsKey = "graphics_settings";
@ -545,7 +545,7 @@ public class GraphicsSettingsManager : Node
#### 音频调试
``csharp
```csharp
// 打印所有音频总线信息
for (int i = 0; i < AudioServer.GetBusCount(); i++)
{
@ -557,7 +557,7 @@ for (int i = 0; i < AudioServer.GetBusCount(); i++)
#### 图形调试
``csharp
```csharp
// 打印当前显示信息
var screen = DisplayServer.GetPrimaryScreen();
var screenSize = DisplayServer.ScreenGetSize(screen);