@@ -32,6 +32,11 @@ def _open_graph(self) -> None:
3232 self .emit ("classDiagram" )
3333 self ._inc_indent ()
3434
35+ def _escape_mermaid_text (self , text : str ) -> str :
36+ """Escape characters that conflict with Markdown formatting."""
37+ text = text .replace ("__" , r"\_\_" ) # Double underscore → escaped
38+ return text
39+
3540 def emit_node (
3641 self ,
3742 name : str ,
@@ -48,14 +53,24 @@ def emit_node(
4853 nodetype = self .NODES [type_ ]
4954 body = []
5055 if properties .attrs :
51- body .extend (properties .attrs )
56+ # Escape attribute names to prevent Markdown formatting issues
57+ escaped_attrs = [
58+ self ._escape_mermaid_text (attr ) for attr in properties .attrs
59+ ]
60+ body .extend (escaped_attrs )
5261 if properties .methods :
5362 for func in properties .methods :
5463 args = self ._get_method_arguments (func )
55- line = f"{ func .name } ({ ', ' .join (args )} )"
64+ # Escape method name and arguments
65+ escaped_method_name = self ._escape_mermaid_text (func .name )
66+ escaped_args = [self ._escape_mermaid_text (arg ) for arg in args ]
67+ line = f"{ escaped_method_name } ({ ', ' .join (escaped_args )} )"
5668 line += "*" if func .is_abstract () else ""
5769 if func .returns :
58- line += f" { get_annotation_label (func .returns )} "
70+ # Escape return type annotation
71+ return_type = get_annotation_label (func .returns )
72+ escaped_return_type = self ._escape_mermaid_text (return_type )
73+ line += f" { escaped_return_type } "
5974 body .append (line )
6075 name = name .split ("." )[- 1 ]
6176 self .emit (f"{ nodetype } { name } {{" )
@@ -77,7 +92,7 @@ def emit_edge(
7792 to_node = to_node .split ("." )[- 1 ]
7893 edge = f"{ from_node } { self .ARROWS [type_ ]} { to_node } "
7994 if label :
80- edge += f" : { label } "
95+ edge += f" : { self . _escape_mermaid_text ( label ) } "
8196 self .emit (edge )
8297
8398 def _close_graph (self ) -> None :
0 commit comments