Create convert_output_to_mermaid.python
Browse files- convert_output_to_mermaid.python +133 -0
convert_output_to_mermaid.python
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
|
3 |
+
|
4 |
+
class MermaidConverter:
|
5 |
+
def __init__(self):
|
6 |
+
# Define style mappings
|
7 |
+
self.style_colors = [
|
8 |
+
{'entity_type':'location', 'node_color':'#264653', 'text_color': '#fff'},
|
9 |
+
{'entity_type':'organization', 'node_color':'#287271', 'text_color': '#fff'},
|
10 |
+
{'entity_type':'person', 'node_color':'#2a9d8f', 'text_color': '#fff'},
|
11 |
+
{'entity_type':'event', 'node_color':'#8ab17d', 'text_color': '#000'},
|
12 |
+
{'entity_type':'object', 'node_color':'#e9c46a', 'text_color': '#000'},
|
13 |
+
{'entity_type':'date', 'node_color':'#f4a261', 'text_color': '#000'},
|
14 |
+
{'entity_type':'skill', 'node_color':'#e76f51', 'text_color': '#000'}
|
15 |
+
]
|
16 |
+
|
17 |
+
# Node name sanitization mapping
|
18 |
+
self.special_chars = str.maketrans("çğıöşüÇĞİÖŞÜ ", "cgioscCGIOSU_")
|
19 |
+
|
20 |
+
def sanitize_node_name(self, name):
|
21 |
+
"""Convert a string into a valid Mermaid node identifier."""
|
22 |
+
return name.translate(self.special_chars)
|
23 |
+
|
24 |
+
def generate_style_definitions(self):
|
25 |
+
"""Generate Mermaid style class definitions."""
|
26 |
+
styles = []
|
27 |
+
for style in self.style_colors:
|
28 |
+
entity_type = style['entity_type']
|
29 |
+
node_color = style['node_color']
|
30 |
+
text_color = style['text_color']
|
31 |
+
|
32 |
+
styles.append(
|
33 |
+
f"classDef {entity_type} fill:{node_color},stroke:#333,stroke-width:2px,color:{text_color};"
|
34 |
+
)
|
35 |
+
return "\n ".join(styles)
|
36 |
+
|
37 |
+
def generate_nodes(self, data):
|
38 |
+
"""Generate Mermaid node definitions."""
|
39 |
+
nodes = []
|
40 |
+
node_mappings = {} # Store sanitized names for relationships
|
41 |
+
|
42 |
+
for node in data['nodes']:
|
43 |
+
name = node['name']
|
44 |
+
node_type = node['type'].lower()
|
45 |
+
sanitized_name = self.sanitize_node_name(name)
|
46 |
+
node_mappings[name] = sanitized_name
|
47 |
+
|
48 |
+
# Create node definition with label showing name and type
|
49 |
+
nodes.append(f'{sanitized_name}(["{name}\\n({node_type})"])')
|
50 |
+
|
51 |
+
return nodes, node_mappings
|
52 |
+
|
53 |
+
def generate_relationships(self, data, node_mappings):
|
54 |
+
"""Generate Mermaid relationship definitions."""
|
55 |
+
relationships = []
|
56 |
+
|
57 |
+
for rel in data['relationships']:
|
58 |
+
source = node_mappings[rel['source']]
|
59 |
+
target = node_mappings[rel['target']]
|
60 |
+
relationship = rel['relationship']
|
61 |
+
|
62 |
+
relationships.append(
|
63 |
+
f'{source} -->|"{relationship}"| {target}'
|
64 |
+
)
|
65 |
+
|
66 |
+
return relationships
|
67 |
+
|
68 |
+
def generate_style_applications(self, data, node_mappings):
|
69 |
+
"""Generate Mermaid style class applications."""
|
70 |
+
# Group nodes by type
|
71 |
+
types = {}
|
72 |
+
for node in data['nodes']:
|
73 |
+
node_type = node['type'].lower()
|
74 |
+
if node_type not in types:
|
75 |
+
types[node_type] = []
|
76 |
+
types[node_type].append(node_mappings[node['name']])
|
77 |
+
|
78 |
+
# Generate style applications
|
79 |
+
style_apps = []
|
80 |
+
for node_type, nodes in types.items():
|
81 |
+
style_apps.append(f"class {','.join(nodes)} {node_type};")
|
82 |
+
|
83 |
+
return style_apps
|
84 |
+
|
85 |
+
def convert(self, data):
|
86 |
+
"""Convert the data dictionary to Mermaid diagram format."""
|
87 |
+
# Generate nodes and get mappings
|
88 |
+
nodes, node_mappings = self.generate_nodes(data)
|
89 |
+
|
90 |
+
# Generate other components
|
91 |
+
relationships = self.generate_relationships(data, node_mappings)
|
92 |
+
style_applications = self.generate_style_applications(data, node_mappings)
|
93 |
+
|
94 |
+
# Construct the complete diagram
|
95 |
+
diagram = [
|
96 |
+
"%%{",
|
97 |
+
" init: {",
|
98 |
+
" 'theme': 'base',",
|
99 |
+
" 'themeVariables': {",
|
100 |
+
" 'primaryTextColor': '#000',",
|
101 |
+
" 'lineColor': '#232323',",
|
102 |
+
" 'secondaryColor': '#ffffff',",
|
103 |
+
" 'tertiaryColor': '#fff'",
|
104 |
+
" }",
|
105 |
+
" }",
|
106 |
+
"}%%",
|
107 |
+
"graph LR",
|
108 |
+
" %% Style definitions",
|
109 |
+
f" {self.generate_style_definitions()}",
|
110 |
+
"",
|
111 |
+
" %% Nodes",
|
112 |
+
" " + "\n ".join(nodes),
|
113 |
+
"",
|
114 |
+
" %% Relationships",
|
115 |
+
" " + "\n ".join(relationships),
|
116 |
+
"",
|
117 |
+
" %% Applying styles",
|
118 |
+
" " + "\n ".join(style_applications)
|
119 |
+
]
|
120 |
+
|
121 |
+
return "\n".join(diagram)
|
122 |
+
|
123 |
+
# Example usage
|
124 |
+
if __name__ == "__main__":
|
125 |
+
|
126 |
+
with open('knowledge_graph.json', 'r', encoding='utf-8') as f:
|
127 |
+
data = json.load(f)
|
128 |
+
|
129 |
+
converter = MermaidConverter()
|
130 |
+
mermaid_diagram = converter.convert(data)
|
131 |
+
|
132 |
+
with open('knowledge_graph.txt', 'w', encoding='utf-8') as f:
|
133 |
+
f.write(mermaid_diagram)
|