1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
"""
Markdown 渲染器
"""
from typing import Any, Dict, List, Union
from .base import BaseRenderer
class MarkdownRenderer(BaseRenderer):
def __init__(self, enable_syntax_hints: bool = True, enable_emoji: bool = True):
super().__init__()
self.enable_syntax_hints = enable_syntax_hints
self.enable_emoji = enable_emoji
self.style = {}
def render(self, data: Union[List[Dict[str, Any]], Dict[str, Any]]) -> str:
if isinstance(data, list):
return self._render_list(data)
elif isinstance(data, dict):
return self._render_dict(data)
else:
return str(data)
def _render_list(self, data: List[Dict[str, Any]]) -> str:
if data and not isinstance(data[0], dict):
data = [{"type": "text", "content": str(item)} for item in data]
stats = self._calculate_stats(data)
emoji_prefix = "🎲 " if self.enable_emoji else ""
md = f"# {emoji_prefix}\n\n"
md += "## Statistics\n\n"
md += "| Type | Count |\n"
md += "|------|------|\n"
md += f"| Total | {stats['total']} |\n"
md += f"| Dialogue | {stats['dialogue']} |\n"
md += f"| Dice | {stats['dice']} |\n"
md += f"| Narration | {stats['narration']} |\n"
md += f"| System | {stats['system']} |\n"
md += f"| Metadata | {stats['metadata']} |\n\n"
md += "---\n\n"
md += "## Detailed Log\n\n"
# Render each token
for i, item in enumerate(data, 1):
md += self._render_token(item, i)
md += "\n"
md += "---\n\n"
md += "_Generated by ConventionalRP Markdown Renderer_\n"
return md
def _render_token(self, token: Dict[str, Any], index: int) -> str:
token_type = token.get("type", "unknown")
# 处理元数据类型(向后兼容)
if token_type == "metadata":
return self._render_metadata_token(token, index)
speaker = token.get("speaker", "")
content = str(token.get("content", ""))
type_emojis = {
"dialogue": "💬",
"dice": "🎲",
"narration": "📖",
"system": "⚙️",
"success": "✅",
"failure": "❌",
"text": "📄",
"unknown": "❓",
}
emoji = type_emojis.get(token_type, "•") if self.enable_emoji else "-"
md = f"### {emoji} [{index}] {token_type.upper()}\n\n"
if speaker:
md += f"**说话者:** {speaker}\n\n"
if token_type == "dice" and self.enable_syntax_hints:
md += f"```dice\n{content}\n```\n\n"
if "result" in token:
md += f"**结果:** `{token['result']}`\n\n"
else:
md += f"{content}\n\n"
metadata_lines = []
if "timestamp" in token:
metadata_lines.append(f"Timestamp: `{token['timestamp']}`")
if "tags" in token and token["tags"]:
tags_str = " ".join([f"`{tag}`" for tag in token["tags"]])
metadata_lines.append(f"Tags: {tags_str}")
if "combat_data" in token:
combat = token["combat_data"]
if combat.get("type") == "damage":
metadata_lines.append(f"Damage: **{combat['amount']}** (Total: {combat.get('total_damage', '?')})")
elif combat.get("type") == "healing":
metadata_lines.append(f"Healing: **{combat['amount']}** (Total: {combat.get('total_healing', '?')})")
if metadata_lines:
md += "> " + "\n> ".join(metadata_lines) + "\n\n"
return md
def _render_metadata_token(self, token: Dict[str, Any], index: int) -> str:
"""渲染元数据类型的 token(向后兼容)"""
md = f"### Entry {index}\n\n"
md += f"**Timestamp**: {token.get('timestamp', 'N/A')} \n"
md += f"**Speaker**: {token.get('speaker', 'N/A')} \n\n"
content_items = token.get("content", [])
if content_items:
md += "**Content**:\n\n"
for content in content_items:
content_type = content.get("type", "unknown")
content_text = content.get("content", "")
md += f"- [{content_type}] {content_text}\n"
md += "\n"
return md
def _render_dict(self, data: Dict[str, Any]) -> str:
markdown_output = ""
for key, value in data.items():
markdown_output += f"## {key}\n\n{value}\n\n"
return markdown_output
def _calculate_stats(self, data: List[Dict[str, Any]]) -> Dict[str, int]:
stats = {
"total": len(data),
"dialogue": 0,
"dice": 0,
"narration": 0,
"system": 0,
"metadata": 0,
}
for item in data:
token_type = item.get("type", "unknown")
if token_type in stats:
stats[token_type] += 1
return stats
def set_style(self, style):
self.style = style
# 从 style 中提取设置
if isinstance(style, dict):
if "emoji" in style:
self.enable_emoji = style["emoji"]
if "syntax_hints" in style:
self.enable_syntax_hints = style["syntax_hints"]
|