Skip to content

Commit b0c467b

Browse files
committed
refactor: render
1 parent 01ad4e6 commit b0c467b

19 files changed

+900
-211
lines changed

docs/changelog.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,11 @@
154154

155155
## 0.15, internal refactor
156156
- 0.15.0
157+
- [x] refactor render.py
158+
- 0.15.1
159+
- [ ] add tests
157160
- [ ] left panel can be toggled.
158161
- [ ] refactor vue-main.js, move methods to store
159-
- [ ] refactor render.py
160-
- [ ] add tests
161162

162163
## 1.0, release
163164

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# Jinja2 模板引擎重构说明
2+
3+
## 概述
4+
5+
已成功将 `render.py` 从硬编码的模板字符串重构为使用 Jinja2 模板引擎的架构。
6+
7+
## 变更内容
8+
9+
### 1. 新增文件
10+
11+
#### `src/fastapi_voyager/render_style.py`
12+
- **ColorScheme**: 颜色配置类(节点、链接、文本颜色)
13+
- **GraphvizStyle**: Graphviz 样式配置类(字体、布局、链接样式)
14+
- **RenderConfig**: 完整的渲染配置类
15+
16+
#### 模板文件
17+
```
18+
templates/
19+
├── dot/ # DOT 格式模板
20+
│ ├── digraph.j2 # 主图模板
21+
│ ├── tag_node.j2 # 标签节点
22+
│ ├── schema_node.j2 # Schema 节点
23+
│ ├── route_node.j2 # 路由节点
24+
│ ├── cluster.j2 # 集群模板
25+
│ ├── cluster_container.j2 # 容器集群
26+
│ └── link.j2 # 链接模板
27+
└── html/ # HTML 格式模板
28+
├── schema_table.j2 # Schema 表格
29+
├── schema_header.j2 # 表格头部
30+
├── schema_field_row.j2 # 字段行
31+
├── pydantic_meta.j2 # Pydantic 元数据
32+
└── colored_text.j2 # 彩色文本
33+
```
34+
35+
### 2. 重构文件
36+
37+
#### `src/fastapi_voyager/render.py`
38+
- **新增 TemplateRenderer 类**: Jinja2 环境管理和模板渲染
39+
- **重构 Renderer 类**:
40+
- 使用模板渲染替代字符串拼接
41+
- 分离关注点(格式化、渲染、配置)
42+
- 保持公共 API 不变,向后兼容
43+
44+
### 3. 依赖更新
45+
46+
#### `pyproject.toml`
47+
```toml
48+
dependencies = [
49+
"fastapi>=0.110",
50+
"pydantic-resolve>=2.4.3",
51+
"jinja2>=3.0.0" # 新增
52+
]
53+
```
54+
55+
## 架构优势
56+
57+
### 1. **关注点分离**
58+
- **逻辑层**: Renderer 类处理业务逻辑
59+
- **视图层**: Jinja2 模板处理格式化
60+
- **配置层**: render_style.py 管理样式常量
61+
62+
### 2. **可维护性提升**
63+
- ✅ 模板集中管理,易于查找和修改
64+
- ✅ 样式常量集中定义
65+
- ✅ 代码结构更清晰
66+
67+
### 3. **可扩展性**
68+
- ✅ 支持主题切换(修改 ColorScheme)
69+
- ✅ 支持自定义配置(注入 RenderConfig)
70+
- ✅ 易于添加新的节点类型或样式
71+
72+
### 4. **可测试性**
73+
- ✅ 模板可独立测试
74+
- ✅ 样式配置可单独验证
75+
- ✅ 渲染逻辑更清晰
76+
77+
## 向后兼容性
78+
79+
**完全兼容**: Renderer 类的公共接口保持不变:
80+
- `__init__()` 参数未变(新增可选的 `config` 参数)
81+
- `render_dot()` 方法签名未变
82+
- 所有渲染方法保持原有行为
83+
84+
## 使用示例
85+
86+
### 基础使用(无变化)
87+
```python
88+
from fastapi_voyager.render import Renderer
89+
90+
renderer = Renderer(
91+
show_fields='all',
92+
module_color={'myapp.services': 'tomato'}
93+
)
94+
dot_output = renderer.render_dot(tags, routes, nodes, links)
95+
```
96+
97+
### 高级使用(新功能)
98+
```python
99+
from fastapi_voyager.render import Renderer
100+
from fastapi_voyager.render_style import RenderConfig, ColorScheme, GraphvizStyle
101+
102+
# 自定义颜色主题
103+
custom_colors = ColorScheme(
104+
primary='#ff6b6b',
105+
highlight='#ffd93d'
106+
)
107+
108+
# 自定义样式
109+
custom_style = GraphvizStyle(
110+
font='Arial',
111+
node_fontsize='14'
112+
)
113+
114+
# 使用自定义配置
115+
config = RenderConfig(colors=custom_colors, style=custom_style)
116+
117+
renderer = Renderer(config=config)
118+
dot_output = renderer.render_dot(tags, routes, nodes, links)
119+
```
120+
121+
## 测试验证
122+
123+
✅ 所有现有测试通过 (18/18)
124+
✅ 模板渲染正确
125+
✅ 向后兼容性验证通过
126+
✅ 实际应用场景测试通过
127+
128+
## 未来改进建议
129+
130+
1. **模板继承**: 使用 Jinja2 模板继承减少重复
131+
2. **主题系统**: 预定义多个主题(深色、浅色、高对比度)
132+
3. **自定义模板**: 支持用户覆盖默认模板
133+
4. **模板验证**: 添加模板语法检查
134+
5. **性能优化**: 缓存编译后的模板
135+
136+
## 迁移指南
137+
138+
### 对于项目维护者
139+
140+
无需修改现有代码,但可选地:
141+
142+
1. **自定义样式**:
143+
```python
144+
from fastapi_voyager.render_style import RenderConfig, ColorScheme
145+
146+
config = RenderConfig(
147+
colors=ColorScheme(primary='#custom-color')
148+
)
149+
renderer = Renderer(config=config)
150+
```
151+
152+
2. **修改模板**:
153+
编辑 `templates/dot/*.j2``templates/html/*.j2` 文件
154+
155+
3. **添加新样式**:
156+
`render_style.py` 中扩展配置类
157+
158+
## 技术细节
159+
160+
### Jinja2 环境配置
161+
```python
162+
Environment(
163+
loader=FileSystemLoader(template_dir),
164+
autoescape=select_autoescape(),
165+
trim_blocks=True, # 移除尾随换行符
166+
lstrip_blocks=True # 移除前导空白
167+
)
168+
```
169+
170+
### 模板路径解析
171+
```python
172+
TEMPLATE_DIR = Path(__file__).parent / "templates"
173+
```
174+
自动定位到 `src/fastapi_voyager/templates/`
175+
176+
## 常见问题
177+
178+
**Q: 为什么要引入 Jinja2?**
179+
A: 将视图模板从业务逻辑中分离,提高代码的可维护性和可扩展性。
180+
181+
**Q: 会影响性能吗?**
182+
A: Jinja2 会编译并缓存模板,性能影响可忽略不计。
183+
184+
**Q: 如何自定义样式?**
185+
A: 使用 RenderConfig 注入自定义配置,或直接修改 render_style.py。
186+
187+
**Q: 模板语法错误如何调试?**
188+
A: Jinja2 会提供详细的错误信息,包括行号和上下文。
189+
190+
## 总结
191+
192+
此次重构成功地将散乱的模板字符串集中管理到 Jinja2 模板文件中,并提取了样式配置到专门的模块。这不仅提高了代码的可维护性,也为未来的功能扩展(如主题系统、自定义模板等)奠定了基础。
193+
194+
**任务完成**: 所有计划任务已完成,测试通过,代码已准备就绪。

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ requires-python = ">=3.10"
99
keywords = ["fastapi", "visualization", "routing", "openapi"]
1010
dependencies = [
1111
"fastapi>=0.110",
12-
"pydantic-resolve>=2.3.1"
12+
"pydantic-resolve>=2.4.3",
13+
"jinja2>=3.0.0"
1314
]
1415
classifiers = [
1516
"Programming Language :: Python :: 3",

0 commit comments

Comments
 (0)