Skip to content

Commit 19e17ee

Browse files
committed
docs: add mermaid modal
Signed-off-by: yuluo-yx <[email protected]>
1 parent c269ba6 commit 19e17ee

File tree

4 files changed

+482
-25
lines changed

4 files changed

+482
-25
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# 可放大 Mermaid 图表组件使用指南
2+
3+
## 概述
4+
5+
`ZoomableMermaid` 组件为 Docusaurus 网站提供了可点击放大的 Mermaid 图表功能。用户可以点击图表在模态框中查看放大版本,提供更好的阅读体验。
6+
7+
## 使用方法
8+
9+
### 基本用法
10+
11+
在任何 Markdown 文档中,首先导入组件:
12+
13+
```jsx
14+
import ZoomableMermaid from '@site/src/components/ZoomableMermaid';
15+
```
16+
17+
然后使用组件包装 Mermaid 图表代码:
18+
19+
```jsx
20+
<ZoomableMermaid title="系统架构图">
21+
{`graph TB
22+
A[开始] --> B[处理]
23+
B --> C[结束]`}
24+
</ZoomableMermaid>
25+
```
26+
27+
### 参数说明
28+
29+
- `children` (string, 必需): Mermaid 图表的代码字符串
30+
- `title` (string, 可选): 图表标题,会显示在模态框顶部
31+
32+
### 功能特性
33+
34+
- **点击放大**: 点击图表在模态框中查看放大版本
35+
- **键盘支持**: 支持 Enter 和空格键打开模态框,Escape 键关闭
36+
- **无障碍访问**: 完整的 ARIA 属性支持
37+
- **响应式设计**: 在各种屏幕尺寸下都能正常工作
38+
- **主题支持**: 自动适应明暗主题
39+
- **动画效果**: 平滑的打开/关闭动画
40+
41+
### 示例
42+
43+
<ZoomableMermaid title="简单流程图">
44+
{`graph LR
45+
A[用户访问] --> B{检查权限}
46+
B -->|有权限| C[显示内容]
47+
B -->|无权限| D[显示错误]`}
48+
</ZoomableMermaid>
49+
50+
## 实现原理
51+
52+
组件基于以下技术栈:
53+
54+
1. **React Hooks**: 使用 `useState``useRef``useEffect` 管理状态
55+
2. **CSS Modules**: 样式隔离和主题支持
56+
3. **事件处理**: 键盘、鼠标和触摸事件
57+
4. **无障碍访问**: ARIA 属性和焦点管理
58+
59+
## 注意事项
60+
61+
- 确保 Mermaid 代码字符串使用模板字符串语法 (backticks)
62+
- 在 JSX 中使用时,需要将代码包装在 `{``}`
63+
- 组件会自动处理焦点管理和页面滚动

website/docs/overview/architecture/system-architecture.md

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ The Semantic Router implements a sophisticated Mixture-of-Models (MoM) architect
44

55
## High-Level Architecture Overview
66

7-
```mermaid
8-
graph TB
7+
import ZoomableMermaid from '@site/src/components/ZoomableMermaid';
8+
9+
<ZoomableMermaid title="System Architecture Overview">
10+
{`graph TB
911
subgraph "Client Layer"
1012
Client1[Web Application]
1113
Client2[Mobile App]
@@ -62,8 +64,8 @@ graph TB
6264

6365
ExtProc --> Prometheus
6466
Prometheus --> Grafana
65-
ExtProc --> Logs
66-
```
67+
ExtProc --> Logs`}
68+
</ZoomableMermaid>
6769

6870
## Core Components
6971

@@ -113,7 +115,7 @@ http_filters:
113115
type OpenAIRouter struct {
114116
Config *config.RouterConfig
115117
CategoryDescriptions []string
116-
Classifier *classification.Classifier // ModernBERT-based
118+
Classifier *classification.Classifier // ModernBERT-based
117119
PIIChecker *pii.PolicyChecker // Privacy protection
118120
Cache *cache.SemanticCache // Performance optimization
119121
ToolsDatabase *tools.ToolsDatabase // Tool selection
@@ -125,8 +127,8 @@ type OpenAIRouter struct {
125127

126128
**Processing Pipeline**:
127129

128-
```mermaid
129-
sequenceDiagram
130+
<ZoomableMermaid title="Processing Pipeline">
131+
{`sequenceDiagram
130132
participant E as Envoy
131133
participant R as Router
132134
participant C as Classifier
@@ -152,17 +154,17 @@ sequenceDiagram
152154
E->>R: Response from model
153155
R->>Ca: Cache semantic representation
154156
R->>E: Final response
155-
end
156-
```
157+
end`}
158+
</ZoomableMermaid>
157159

158160
### 3. Classification System - Decision Engine
159161

160162
The classification system uses ModernBERT models for multiple classification tasks:
161163

162164
#### Category Classification
163165

164-
```mermaid
165-
graph LR
166+
<ZoomableMermaid title="Category Classification System">
167+
{`graph LR
166168
Query[User Query] --> Tokenizer[ModernBERT Tokenizer]
167169
Tokenizer --> Encoder[ModernBERT Encoder<br/>768-dim embeddings]
168170
Encoder --> ClassifierHead[Classification Head<br/>Category Prediction]
@@ -182,8 +184,8 @@ graph LR
182184
Decision --> Code
183185
Decision --> General
184186
Decision --> Science
185-
Decision --> Business
186-
```
187+
Decision --> Business`}
188+
</ZoomableMermaid>
187189

188190
#### Multi-Task Architecture
189191

@@ -214,8 +216,8 @@ class SemanticRouter:
214216

215217
### Request Processing Flow
216218

217-
```mermaid
218-
graph TB
219+
<ZoomableMermaid title="Request Processing Flow">
220+
{`graph TB
219221
Start([Client Request]) --> EnvoyReceive[Envoy Receives Request]
220222

221223
EnvoyReceive --> ExtProcSend[Send to ExtProc<br/>Headers + Body]
@@ -257,13 +259,13 @@ graph TB
257259
style JailbreakCheck fill:#f44336
258260
style CategoryClassification fill:#4caf50
259261
style CacheCheck fill:#2196f3
260-
style RoutingDecision fill:#9c27b0
261-
```
262+
style RoutingDecision fill:#9c27b0`}
263+
</ZoomableMermaid>
262264

263265
### Response Processing Flow
264266

265-
```mermaid
266-
sequenceDiagram
267+
<ZoomableMermaid title="Response Processing Flow">
268+
{`sequenceDiagram
267269
participant C as Client
268270
participant E as Envoy
269271
participant R as Router
@@ -285,8 +287,8 @@ sequenceDiagram
285287
R->>Me: Record routing metrics
286288

287289
R->>E: Processed Response
288-
E->>C: Final Response to Client
289-
```
290+
E->>C: Final Response to Client`}
291+
</ZoomableMermaid>
290292

291293
## Threading and Concurrency Model
292294

@@ -514,8 +516,8 @@ func (cb *CircuitBreaker) Call(operation func() error) error {
514516

515517
### Fallback Strategies
516518

517-
```mermaid
518-
graph TB
519+
<ZoomableMermaid title="Fallback Strategies">
520+
{`graph TB
519521
Request[Incoming Request] --> PrimaryRoute[Primary Routing Decision]
520522

521523
PrimaryRoute --> ModelA{Model A<br/>Available?}
@@ -534,8 +536,8 @@ graph TB
534536
ProcessA --> Success[Successful Response]
535537
ProcessB --> Success
536538
ProcessGeneral --> Success
537-
ReturnCached --> Success
538-
```
539+
ReturnCached --> Success`}
540+
</ZoomableMermaid>
539541

540542
## Monitoring and Observability
541543

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import React, { useState, useRef, useEffect, useCallback } from 'react';
2+
import Mermaid from '@theme/Mermaid';
3+
import styles from './styles.module.css';
4+
5+
const ZoomableMermaid = ({ children, title }) => {
6+
const [isModalOpen, setIsModalOpen] = useState(false);
7+
const [isHovered, setIsHovered] = useState(false);
8+
const modalRef = useRef(null);
9+
const containerRef = useRef(null);
10+
11+
const openModal = useCallback(() => {
12+
setIsModalOpen(true);
13+
document.body.style.overflow = 'hidden';
14+
}, []);
15+
16+
const closeModal = useCallback(() => {
17+
setIsModalOpen(false);
18+
document.body.style.overflow = 'unset';
19+
// Return focus to the original container
20+
if (containerRef.current) {
21+
containerRef.current.focus();
22+
}
23+
}, []);
24+
25+
useEffect(() => {
26+
const handleEscape = (e) => {
27+
if (e.key === 'Escape' && isModalOpen) {
28+
closeModal();
29+
}
30+
};
31+
32+
const handleClickOutside = (e) => {
33+
if (modalRef.current && !modalRef.current.contains(e.target)) {
34+
closeModal();
35+
}
36+
};
37+
38+
if (isModalOpen) {
39+
document.addEventListener('keydown', handleEscape);
40+
document.addEventListener('mousedown', handleClickOutside);
41+
42+
// Focus the modal content when opened
43+
setTimeout(() => {
44+
if (modalRef.current) {
45+
modalRef.current.focus();
46+
}
47+
}, 100);
48+
}
49+
50+
return () => {
51+
document.removeEventListener('keydown', handleEscape);
52+
document.removeEventListener('mousedown', handleClickOutside);
53+
};
54+
}, [isModalOpen, closeModal]);
55+
56+
// Cleanup on unmount
57+
useEffect(() => {
58+
return () => {
59+
document.body.style.overflow = 'unset';
60+
};
61+
}, []);
62+
63+
const handleKeyDown = (e) => {
64+
if (e.key === 'Enter' || e.key === ' ') {
65+
e.preventDefault();
66+
openModal();
67+
}
68+
};
69+
70+
return (
71+
<>
72+
<div
73+
ref={containerRef}
74+
className={`${styles.mermaidContainer} ${isHovered ? styles.hovered : ''}`}
75+
onClick={openModal}
76+
onMouseEnter={() => setIsHovered(true)}
77+
onMouseLeave={() => setIsHovered(false)}
78+
role="button"
79+
tabIndex={0}
80+
onKeyDown={handleKeyDown}
81+
aria-label={`点击放大查看 ${title || 'Mermaid 图表'}`}
82+
aria-expanded={isModalOpen}
83+
>
84+
<div className={styles.zoomHint} aria-hidden="true">
85+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
86+
<circle cx="11" cy="11" r="8"/>
87+
<path d="m21 21-4.35-4.35"/>
88+
<path d="M11 8v6"/>
89+
<path d="M8 11h6"/>
90+
</svg>
91+
<span>点击放大</span>
92+
</div>
93+
<Mermaid value={children} />
94+
</div>
95+
96+
{isModalOpen && (
97+
<div
98+
className={styles.modal}
99+
role="dialog"
100+
aria-modal="true"
101+
aria-labelledby={title ? "modal-title" : undefined}
102+
aria-describedby="modal-description"
103+
>
104+
<div
105+
className={styles.modalContent}
106+
ref={modalRef}
107+
tabIndex={-1}
108+
>
109+
<div className={styles.modalHeader}>
110+
{title && (
111+
<h3 id="modal-title" className={styles.modalTitle}>
112+
{title}
113+
</h3>
114+
)}
115+
<button
116+
className={styles.closeButton}
117+
onClick={closeModal}
118+
aria-label="关闭放大视图"
119+
type="button"
120+
>
121+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
122+
<line x1="18" y1="6" x2="6" y2="18"/>
123+
<line x1="6" y1="6" x2="18" y2="18"/>
124+
</svg>
125+
</button>
126+
</div>
127+
<div
128+
className={styles.modalBody}
129+
id="modal-description"
130+
aria-label="放大的 Mermaid 图表"
131+
>
132+
<Mermaid value={children} />
133+
</div>
134+
</div>
135+
</div>
136+
)}
137+
</>
138+
);
139+
};
140+
141+
export default ZoomableMermaid;

0 commit comments

Comments
 (0)