diff --git a/backend/app/api/chat.py b/backend/app/api/chat.py index 62e59cf..4958a13 100644 --- a/backend/app/api/chat.py +++ b/backend/app/api/chat.py @@ -396,6 +396,30 @@ def _transform_mindmaps(text: str) -> str: return _FENCE_RE.sub(_repl, text) +_LABEL_QUOTES = {"d": True, "s": True} + + +def _safe_label(label: str) -> str: + """把会破坏老版 mermaid flowchart 语法的字符替换为可安全渲染的等价字符。 + + - ASCII 双/单引号 → 弯引号(“”/‘’):老版 mermaid 不认 ["...\\"..."] 转义, + 引号会把字符串截断导致 Parse error;弯引号是普通 Unicode,可正常渲染且保留语义。 + - 反斜杠 → 斜杠;# → 全角#(老版 mermaid 中 # 有特殊含义)。 + """ + states = dict(_LABEL_QUOTES) + + def _rep(m: re.Match) -> str: + ch = m.group(0) + key = "d" if ch == '"' else "s" + pair = ("“", "”") if key == "d" else ("‘", "’") + idx = 0 if states[key] else 1 + states[key] = not states[key] + return pair[idx] + + label = re.sub(r'["\']', _rep, label) + return label.replace("\\", "/").replace("#", "#") + + def _mindmap_to_flowchart(body: str) -> str: """mindmap(缩进式)→ flowchart LR(节点 + 边)。 @@ -448,7 +472,7 @@ def _mindmap_to_flowchart(body: str) -> str: while stack and stack[-1][0] >= indent_len: stack.pop() nid = _new_id() - safe = label.replace("\\", "\\\\").replace('"', '\\"').replace("\n", " ") + safe = _safe_label(label).replace("\n", " ") out.append(f' {nid}["{safe}"]') if stack: out.append(f" {stack[-1][1]} --> {nid}")