sayou-visualizer 0.0.11__py3-none-any.whl → 0.0.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sayou/visualizer/core/styles.py +223 -0
- sayou/visualizer/pipeline.py +1 -1
- sayou/visualizer/renderer/analytic_kg_renderer.py +17 -185
- sayou/visualizer/renderer/showcase_kg_renderer.py +36 -39
- {sayou_visualizer-0.0.11.dist-info → sayou_visualizer-0.0.12.dist-info}/METADATA +1 -1
- {sayou_visualizer-0.0.11.dist-info → sayou_visualizer-0.0.12.dist-info}/RECORD +7 -6
- {sayou_visualizer-0.0.11.dist-info → sayou_visualizer-0.0.12.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
from sayou.core.ontology import SayouClass
|
|
2
|
+
|
|
3
|
+
HIDDEN_ATTR_PREFIXES = ["sayou:", "meta:", "schema:"]
|
|
4
|
+
|
|
5
|
+
# =========================================================
|
|
6
|
+
# 1. 3D Showcase Styles (Original Design Restored)
|
|
7
|
+
# =========================================================
|
|
8
|
+
SHOWCASE_STYLE_MAP = {
|
|
9
|
+
"default": {"group": "Chunk", "color": "#4a69bd", "val": 3},
|
|
10
|
+
# [Original Design Colors]
|
|
11
|
+
SayouClass.FILE: {"group": "Document", "color": "#00d2d3", "val": 20}, # Cyan
|
|
12
|
+
SayouClass.CLASS: {"group": "Header", "color": "#ff6b81", "val": 12}, # Pink
|
|
13
|
+
SayouClass.METHOD: {"group": "Code", "color": "#feca57", "val": 6}, # Gold
|
|
14
|
+
SayouClass.FUNCTION: {"group": "Code", "color": "#feca57", "val": 6}, # Gold
|
|
15
|
+
SayouClass.LIBRARY: {"group": "Library", "color": "#2ed573", "val": 10}, # Green
|
|
16
|
+
# [New] YouTube Domain (Compatible Theme)
|
|
17
|
+
SayouClass.VIDEO: {"group": "Video", "color": "#e84118", "val": 40}, # Deep Red
|
|
18
|
+
SayouClass.VIDEO_SEGMENT: {
|
|
19
|
+
"group": "Segment",
|
|
20
|
+
"color": "#dcdde1",
|
|
21
|
+
"val": 4,
|
|
22
|
+
}, # Gray
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# 동적 크기 계산 규칙
|
|
26
|
+
DYNAMIC_SIZING_RULES = {
|
|
27
|
+
SayouClass.VIDEO_SEGMENT: {
|
|
28
|
+
"attr_start": "sayou:startTime",
|
|
29
|
+
"attr_end": "sayou:endTime",
|
|
30
|
+
"base_val": 4,
|
|
31
|
+
"scale_factor": 0.5,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# =========================================================
|
|
36
|
+
# 2. 2D Analyst Styles (Original Design + Interactions Restored)
|
|
37
|
+
# =========================================================
|
|
38
|
+
ANALYST_TYPE_MAPPING = {
|
|
39
|
+
SayouClass.FILE: "file",
|
|
40
|
+
SayouClass.CLASS: "class",
|
|
41
|
+
SayouClass.METHOD: "method",
|
|
42
|
+
SayouClass.FUNCTION: "function",
|
|
43
|
+
SayouClass.LIBRARY: "library",
|
|
44
|
+
SayouClass.CODE_BLOCK: "code_block",
|
|
45
|
+
SayouClass.VIDEO: "video",
|
|
46
|
+
SayouClass.VIDEO_SEGMENT: "segment",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
ANALYST_STYLE_SHEET = [
|
|
50
|
+
# [Global]
|
|
51
|
+
{
|
|
52
|
+
"selector": "node",
|
|
53
|
+
"style": {
|
|
54
|
+
"label": "data(label)",
|
|
55
|
+
"color": "#ecf0f1",
|
|
56
|
+
"font-size": "10px",
|
|
57
|
+
"text-valign": "center",
|
|
58
|
+
"text-halign": "center",
|
|
59
|
+
"text-wrap": "wrap",
|
|
60
|
+
"text-max-width": "100px",
|
|
61
|
+
"background-color": "#95a5a6",
|
|
62
|
+
"border-width": 1,
|
|
63
|
+
"border-color": "#7f8c8d",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
# [Original Node Shapes/Colors]
|
|
67
|
+
{
|
|
68
|
+
"selector": "node[type='file']",
|
|
69
|
+
"style": {
|
|
70
|
+
"shape": "rectangle",
|
|
71
|
+
"background-color": "#2c3e50",
|
|
72
|
+
"width": 60,
|
|
73
|
+
"height": 60,
|
|
74
|
+
"font-size": "12px",
|
|
75
|
+
"font-weight": "bold",
|
|
76
|
+
"border-width": 2,
|
|
77
|
+
"border-color": "#00d2d3",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"selector": "node[type='class']",
|
|
82
|
+
"style": {
|
|
83
|
+
"shape": "diamond",
|
|
84
|
+
"background-color": "#8e44ad",
|
|
85
|
+
"width": 40,
|
|
86
|
+
"height": 40,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"selector": "node[type='method'], node[type='function']",
|
|
91
|
+
"style": {
|
|
92
|
+
"shape": "ellipse",
|
|
93
|
+
"background-color": "#e67e22",
|
|
94
|
+
"width": 25,
|
|
95
|
+
"height": 25,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"selector": "node[type='code_block']",
|
|
100
|
+
"style": {
|
|
101
|
+
"shape": "round-rectangle",
|
|
102
|
+
"background-color": "#7f8c8d",
|
|
103
|
+
"width": 15,
|
|
104
|
+
"height": 15,
|
|
105
|
+
"label": "",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"selector": "node[type='library']",
|
|
110
|
+
"style": {
|
|
111
|
+
"shape": "hexagon",
|
|
112
|
+
"background-color": "#16a085",
|
|
113
|
+
"width": 50,
|
|
114
|
+
"height": 50,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
# [New YouTube Nodes]
|
|
118
|
+
{
|
|
119
|
+
"selector": "node[type='video']",
|
|
120
|
+
"style": {
|
|
121
|
+
"shape": "rectangle",
|
|
122
|
+
"background-color": "#c0392b",
|
|
123
|
+
"width": 80,
|
|
124
|
+
"height": 80,
|
|
125
|
+
"border-width": 4,
|
|
126
|
+
"border-color": "#e74c3c",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"selector": "node[type='segment']",
|
|
131
|
+
"style": {
|
|
132
|
+
"shape": "round-rectangle",
|
|
133
|
+
"background-color": "#bdc3c7",
|
|
134
|
+
"width": 40,
|
|
135
|
+
"height": 20,
|
|
136
|
+
"color": "#2c3e50",
|
|
137
|
+
"font-size": "8px",
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
# [Original Edges]
|
|
141
|
+
{
|
|
142
|
+
"selector": "edge",
|
|
143
|
+
"style": {
|
|
144
|
+
"width": 1,
|
|
145
|
+
"curve-style": "bezier",
|
|
146
|
+
"opacity": 0.6,
|
|
147
|
+
"arrow-scale": 1,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"selector": "edge[edgeType='sayou:contains']",
|
|
152
|
+
"style": {
|
|
153
|
+
"line-color": "#7f8c8d",
|
|
154
|
+
"target-arrow-shape": "circle",
|
|
155
|
+
"line-style": "dashed",
|
|
156
|
+
"width": 1.5,
|
|
157
|
+
"opacity": 0.7,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"selector": "edge[edgeType='sayou:imports']",
|
|
162
|
+
"style": {
|
|
163
|
+
"line-color": "#00d2d3",
|
|
164
|
+
"target-arrow-shape": "triangle",
|
|
165
|
+
"line-style": "dashed",
|
|
166
|
+
"width": 2,
|
|
167
|
+
"opacity": 0.9,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"selector": "edge[edgeType='sayou:inherits']",
|
|
172
|
+
"style": {
|
|
173
|
+
"line-color": "#ff6b6b",
|
|
174
|
+
"target-arrow-shape": "triangle",
|
|
175
|
+
"width": 3,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"selector": "edge[edgeType='sayou:next']",
|
|
180
|
+
"style": {
|
|
181
|
+
"line-color": "#f39c12",
|
|
182
|
+
"target-arrow-shape": "triangle",
|
|
183
|
+
"width": 2,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
# =========================================================
|
|
187
|
+
# [CRITICAL FIX] Restored Interaction Styles
|
|
188
|
+
# =========================================================
|
|
189
|
+
{
|
|
190
|
+
"selector": ".highlighted",
|
|
191
|
+
"style": {
|
|
192
|
+
"background-color": "#f1c40f",
|
|
193
|
+
"line-color": "#f1c40f",
|
|
194
|
+
"target-arrow-color": "#f1c40f",
|
|
195
|
+
"opacity": 1,
|
|
196
|
+
"z-index": 999,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"selector": ".faded",
|
|
201
|
+
"style": {"opacity": 0.05, "label": ""},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"selector": ".found",
|
|
205
|
+
"style": {
|
|
206
|
+
"border-width": 4,
|
|
207
|
+
"border-color": "#e056fd",
|
|
208
|
+
"background-color": "#e056fd",
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"selector": "node.no-label",
|
|
213
|
+
"style": {
|
|
214
|
+
"text-opacity": 0,
|
|
215
|
+
"text-background-opacity": 0,
|
|
216
|
+
"text-border-opacity": 0,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"selector": "edge.hidden-edge",
|
|
221
|
+
"style": {"display": "none"},
|
|
222
|
+
},
|
|
223
|
+
]
|
sayou/visualizer/pipeline.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from sayou.core.base_component import BaseComponent
|
|
2
2
|
|
|
3
3
|
from .renderer.analytic_kg_renderer import AnalyticKGRenderer
|
|
4
|
-
from .renderer.showcase_kg_renderer import ShowcaseKGRenderer
|
|
5
4
|
from .renderer.pyvis_renderer import PyVisRenderer
|
|
5
|
+
from .renderer.showcase_kg_renderer import ShowcaseKGRenderer
|
|
6
6
|
from .tracer.graph_tracer import GraphTracer
|
|
7
7
|
from .tracer.rich_tracer import RichConsoleTracer
|
|
8
8
|
from .tracer.websocket_tracer import WebSocketTracer
|
|
@@ -3,6 +3,8 @@ import os
|
|
|
3
3
|
|
|
4
4
|
from sayou.core.base_component import BaseComponent
|
|
5
5
|
|
|
6
|
+
from ..core.styles import ANALYST_STYLE_SHEET, ANALYST_TYPE_MAPPING
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
class AnalyticKGRenderer(BaseComponent):
|
|
8
10
|
"""
|
|
@@ -15,158 +17,7 @@ class AnalyticKGRenderer(BaseComponent):
|
|
|
15
17
|
|
|
16
18
|
component_name = "AnalyticKGRenderer"
|
|
17
19
|
|
|
18
|
-
STYLE_SHEET =
|
|
19
|
-
# [Global Nodes]
|
|
20
|
-
{
|
|
21
|
-
"selector": "node",
|
|
22
|
-
"style": {
|
|
23
|
-
"label": "data(label)",
|
|
24
|
-
"color": "#ecf0f1",
|
|
25
|
-
"font-size": "10px",
|
|
26
|
-
"text-valign": "center",
|
|
27
|
-
"text-halign": "center",
|
|
28
|
-
"text-wrap": "wrap",
|
|
29
|
-
"text-max-width": "100px",
|
|
30
|
-
"background-color": "#95a5a6",
|
|
31
|
-
"border-width": 1,
|
|
32
|
-
"border-color": "#7f8c8d",
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
# [File Node]
|
|
36
|
-
{
|
|
37
|
-
"selector": "node[type='file']",
|
|
38
|
-
"style": {
|
|
39
|
-
"shape": "rectangle",
|
|
40
|
-
"background-color": "#2c3e50",
|
|
41
|
-
"width": 60,
|
|
42
|
-
"height": 60,
|
|
43
|
-
"font-size": "12px",
|
|
44
|
-
"font-weight": "bold",
|
|
45
|
-
"border-width": 2,
|
|
46
|
-
"border-color": "#00d2d3",
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
# [Class Node]
|
|
50
|
-
{
|
|
51
|
-
"selector": "node[type='class']",
|
|
52
|
-
"style": {
|
|
53
|
-
"shape": "diamond",
|
|
54
|
-
"background-color": "#8e44ad",
|
|
55
|
-
"width": 40,
|
|
56
|
-
"height": 40,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
# [Method/Function]
|
|
60
|
-
{
|
|
61
|
-
"selector": "node[type='method'], node[type='function']",
|
|
62
|
-
"style": {
|
|
63
|
-
"shape": "ellipse",
|
|
64
|
-
"background-color": "#e67e22",
|
|
65
|
-
"width": 25,
|
|
66
|
-
"height": 25,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
# [Code Chunk]
|
|
70
|
-
{
|
|
71
|
-
"selector": "node[type='code_block']",
|
|
72
|
-
"style": {
|
|
73
|
-
"shape": "round-rectangle",
|
|
74
|
-
"background-color": "#7f8c8d",
|
|
75
|
-
"width": 15,
|
|
76
|
-
"height": 15,
|
|
77
|
-
"label": "",
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
# [Package/Library]
|
|
81
|
-
{
|
|
82
|
-
"selector": "node[type='library'], node[type='package']",
|
|
83
|
-
"style": {
|
|
84
|
-
"shape": "hexagon",
|
|
85
|
-
"background-color": "#16a085",
|
|
86
|
-
"width": 50,
|
|
87
|
-
"height": 50,
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
# [Edges]
|
|
91
|
-
{
|
|
92
|
-
"selector": "edge",
|
|
93
|
-
"style": {
|
|
94
|
-
"width": 1,
|
|
95
|
-
"curve-style": "bezier",
|
|
96
|
-
"opacity": 0.6,
|
|
97
|
-
"arrow-scale": 1,
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
# 1. Structure Line (contains) -> Gray Dashed Line (Skeleton)
|
|
101
|
-
{
|
|
102
|
-
"selector": "edge[edgeType='sayou:contains']",
|
|
103
|
-
"style": {
|
|
104
|
-
"line-color": "#7f8c8d",
|
|
105
|
-
"target-arrow-color": "#7f8c8d",
|
|
106
|
-
"target-arrow-shape": "circle",
|
|
107
|
-
"width": 1.5,
|
|
108
|
-
"line-style": "dashed",
|
|
109
|
-
"opacity": 0.7,
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
# 2. Logic Line (imports) -> Cyan Dashed Line (Flow)
|
|
113
|
-
{
|
|
114
|
-
"selector": "edge[edgeType='sayou:imports']",
|
|
115
|
-
"style": {
|
|
116
|
-
"line-color": "#00d2d3",
|
|
117
|
-
"target-arrow-color": "#00d2d3",
|
|
118
|
-
"target-arrow-shape": "triangle",
|
|
119
|
-
"line-style": "dashed",
|
|
120
|
-
"width": 2,
|
|
121
|
-
"opacity": 0.9,
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
# 3. Inheritance Line (inherits) -> Red Solid Line
|
|
125
|
-
{
|
|
126
|
-
"selector": "edge[edgeType='sayou:inherits']",
|
|
127
|
-
"style": {
|
|
128
|
-
"line-color": "#ff6b6b",
|
|
129
|
-
"target-arrow-color": "#ff6b6b",
|
|
130
|
-
"target-arrow-shape": "triangle",
|
|
131
|
-
"width": 3,
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
# [Interaction]
|
|
135
|
-
{
|
|
136
|
-
"selector": ".highlighted",
|
|
137
|
-
"style": {
|
|
138
|
-
"background-color": "#f1c40f",
|
|
139
|
-
"line-color": "#f1c40f",
|
|
140
|
-
"target-arrow-color": "#f1c40f",
|
|
141
|
-
"opacity": 1,
|
|
142
|
-
"z-index": 999,
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
"selector": ".faded",
|
|
147
|
-
"style": {"opacity": 0.05, "label": ""},
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
"selector": ".found",
|
|
151
|
-
"style": {
|
|
152
|
-
"border-width": 4,
|
|
153
|
-
"border-color": "#e056fd",
|
|
154
|
-
"background-color": "#e056fd",
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"selector": "node.no-label",
|
|
159
|
-
"style": {
|
|
160
|
-
"text-opacity": 0,
|
|
161
|
-
"text-background-opacity": 0,
|
|
162
|
-
"text-border-opacity": 0,
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"selector": "edge.hidden-edge",
|
|
167
|
-
"style": {"display": "none"},
|
|
168
|
-
},
|
|
169
|
-
]
|
|
20
|
+
STYLE_SHEET = ANALYST_STYLE_SHEET
|
|
170
21
|
|
|
171
22
|
def render(self, json_path: str, output_path: str = "sayou_analyst_view.html"):
|
|
172
23
|
if not os.path.exists(json_path):
|
|
@@ -177,57 +28,38 @@ class AnalyticKGRenderer(BaseComponent):
|
|
|
177
28
|
|
|
178
29
|
elements = []
|
|
179
30
|
|
|
180
|
-
# 1. Nodes
|
|
31
|
+
# 1. Nodes Processing
|
|
181
32
|
for node in raw_data.get("nodes", []):
|
|
182
33
|
node_id = node.get("node_id")
|
|
183
34
|
attrs = node.get("attributes", {})
|
|
184
|
-
n_cls = node.get("node_class", "unknown")
|
|
185
|
-
|
|
186
|
-
#
|
|
187
|
-
cy_type = "unknown"
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
elif "method" in n_cls:
|
|
193
|
-
cy_type = "method"
|
|
194
|
-
elif "function" in n_cls:
|
|
195
|
-
cy_type = "function"
|
|
196
|
-
elif "library" in n_cls:
|
|
197
|
-
cy_type = "library"
|
|
198
|
-
elif "code" in n_cls:
|
|
199
|
-
cy_type = "code_block"
|
|
200
|
-
|
|
201
|
-
# Labeling
|
|
202
|
-
label = attrs.get("label") or node.get("friendly_name") or node_id
|
|
203
|
-
if cy_type == "file":
|
|
204
|
-
label = os.path.basename(attrs.get("sayou:filePath", label))
|
|
205
|
-
elif cy_type == "class":
|
|
206
|
-
label = attrs.get("meta:class_name", label)
|
|
207
|
-
elif cy_type in ["method", "function"]:
|
|
208
|
-
label = attrs.get("function_name", label)
|
|
209
|
-
|
|
210
|
-
# Code Text
|
|
211
|
-
code_text = attrs.get("schema:text", "")
|
|
35
|
+
n_cls = node.get("node_class", "unknown")
|
|
36
|
+
|
|
37
|
+
# [Pure Config Lookup]
|
|
38
|
+
cy_type = ANALYST_TYPE_MAPPING.get(n_cls, "unknown")
|
|
39
|
+
|
|
40
|
+
# [No Logic] Builder가 준 라벨을 그대로 사용
|
|
41
|
+
label = node.get("friendly_name") or attrs.get("label") or node_id
|
|
42
|
+
|
|
212
43
|
cy_data = {
|
|
213
44
|
"id": node_id,
|
|
214
45
|
"label": label,
|
|
215
46
|
"type": cy_type,
|
|
216
|
-
"code":
|
|
47
|
+
"code": attrs.get("schema:text", ""),
|
|
217
48
|
"meta": attrs,
|
|
218
49
|
}
|
|
219
50
|
elements.append({"group": "nodes", "data": cy_data})
|
|
220
51
|
|
|
221
|
-
# 2. Edges
|
|
52
|
+
# 2. Edges Processing
|
|
222
53
|
for edge in raw_data.get("edges", []):
|
|
54
|
+
e_type = edge.get("type", "relates")
|
|
223
55
|
elements.append(
|
|
224
56
|
{
|
|
225
57
|
"group": "edges",
|
|
226
58
|
"data": {
|
|
227
59
|
"source": edge.get("source"),
|
|
228
60
|
"target": edge.get("target"),
|
|
229
|
-
"edgeType":
|
|
230
|
-
"label":
|
|
61
|
+
"edgeType": e_type,
|
|
62
|
+
"label": e_type.split(":")[-1],
|
|
231
63
|
},
|
|
232
64
|
}
|
|
233
65
|
)
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
|
|
3
4
|
from sayou.core.base_component import BaseComponent
|
|
4
5
|
|
|
6
|
+
from ..core.styles import HIDDEN_ATTR_PREFIXES, SHOWCASE_STYLE_MAP
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
class ShowcaseKGRenderer(BaseComponent):
|
|
7
10
|
"""
|
|
@@ -15,6 +18,7 @@ class ShowcaseKGRenderer(BaseComponent):
|
|
|
15
18
|
|
|
16
19
|
def render(self, json_path: str, output_path: str = "sayou_showcase_3d.html"):
|
|
17
20
|
if not os.path.exists(json_path):
|
|
21
|
+
self._log(f"❌ File not found: {json_path}", level="error")
|
|
18
22
|
return
|
|
19
23
|
|
|
20
24
|
with open(json_path, "r", encoding="utf-8") as f:
|
|
@@ -24,64 +28,44 @@ class ShowcaseKGRenderer(BaseComponent):
|
|
|
24
28
|
links = []
|
|
25
29
|
existing_ids = set()
|
|
26
30
|
|
|
31
|
+
# 1. Nodes Processing
|
|
27
32
|
for node in raw_data.get("nodes", []):
|
|
28
33
|
node_id = node.get("node_id")
|
|
34
|
+
if not node_id:
|
|
35
|
+
continue
|
|
29
36
|
existing_ids.add(node_id)
|
|
37
|
+
|
|
30
38
|
attrs = node.get("attributes", {})
|
|
31
|
-
n_cls = node.get("node_class", "unknown")
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
val =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
val = 20
|
|
41
|
-
elif "class" in n_cls:
|
|
42
|
-
group = "Header"
|
|
43
|
-
color = "#ff6b81" # Pink
|
|
44
|
-
val = 12
|
|
45
|
-
elif "method" in n_cls or "function" in n_cls:
|
|
46
|
-
group = "Code"
|
|
47
|
-
color = "#feca57" # Gold
|
|
48
|
-
val = 6
|
|
49
|
-
elif "library" in n_cls:
|
|
50
|
-
group = "Library"
|
|
51
|
-
color = "#2ed573" # Green
|
|
52
|
-
val = 10
|
|
53
|
-
|
|
54
|
-
label = attrs.get("label") or node.get("friendly_name") or node_id
|
|
55
|
-
if group == "Document":
|
|
56
|
-
label = os.path.basename(attrs.get("sayou:filePath", label))
|
|
57
|
-
|
|
58
|
-
clean_attrs = {}
|
|
59
|
-
for k, v in attrs.items():
|
|
60
|
-
if isinstance(v, str) and len(v) > 200:
|
|
61
|
-
clean_attrs[k] = v[:200] + "..."
|
|
62
|
-
elif not k.startswith("sayou:"):
|
|
63
|
-
clean_attrs[k] = v
|
|
39
|
+
n_cls = node.get("node_class", "unknown")
|
|
40
|
+
|
|
41
|
+
style = SHOWCASE_STYLE_MAP.get(n_cls, SHOWCASE_STYLE_MAP["default"])
|
|
42
|
+
|
|
43
|
+
val = attrs.get("val", style["val"])
|
|
44
|
+
|
|
45
|
+
label = node.get("friendly_name") or attrs.get("label") or node_id
|
|
46
|
+
|
|
47
|
+
clean_attrs = self._clean_attributes(attrs)
|
|
64
48
|
|
|
65
49
|
nodes.append(
|
|
66
50
|
{
|
|
67
51
|
"id": node_id,
|
|
68
52
|
"label": label,
|
|
69
|
-
"group": group,
|
|
70
|
-
"color": color,
|
|
53
|
+
"group": style["group"],
|
|
54
|
+
"color": style["color"],
|
|
71
55
|
"val": val,
|
|
72
56
|
"attributes": clean_attrs,
|
|
73
57
|
}
|
|
74
58
|
)
|
|
75
59
|
|
|
76
|
-
#
|
|
60
|
+
# 2. Edges Processing
|
|
77
61
|
for edge in raw_data.get("edges", []):
|
|
78
62
|
src = edge.get("source")
|
|
79
63
|
tgt = edge.get("target")
|
|
80
|
-
|
|
81
64
|
if src in existing_ids and tgt in existing_ids:
|
|
82
65
|
e_type = edge.get("type", "relates")
|
|
83
|
-
is_import =
|
|
84
|
-
|
|
66
|
+
is_import = any(
|
|
67
|
+
k in e_type for k in ["import", "calls", "next", "contains"]
|
|
68
|
+
)
|
|
85
69
|
links.append(
|
|
86
70
|
{
|
|
87
71
|
"source": src,
|
|
@@ -95,6 +79,19 @@ class ShowcaseKGRenderer(BaseComponent):
|
|
|
95
79
|
self._generate_html(graph_data, output_path)
|
|
96
80
|
self._log(f"✅ Final Visual Showcase generated at: {output_path}")
|
|
97
81
|
|
|
82
|
+
def _clean_attributes(self, attrs):
|
|
83
|
+
"""설정 파일 기반 속성 정제"""
|
|
84
|
+
clean = {}
|
|
85
|
+
for k, v in attrs.items():
|
|
86
|
+
if any(k.startswith(prefix) for prefix in HIDDEN_ATTR_PREFIXES):
|
|
87
|
+
continue
|
|
88
|
+
s = str(v)
|
|
89
|
+
if len(s) > 200:
|
|
90
|
+
clean[k] = s[:200] + "..."
|
|
91
|
+
else:
|
|
92
|
+
clean[k] = v
|
|
93
|
+
return clean
|
|
94
|
+
|
|
98
95
|
def _generate_html(self, graph_data, output_path):
|
|
99
96
|
json_str = json.dumps(graph_data)
|
|
100
97
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
sayou/visualizer/__init__.py,sha256=DRv-5qzP6nal7qXVf7Zl67CQx3Kf3mTZhlLKl-vs_G0,82
|
|
2
|
-
sayou/visualizer/pipeline.py,sha256=
|
|
2
|
+
sayou/visualizer/pipeline.py,sha256=NWeIwQqp6ctP-xnhYEPdRwcLQ0RkYSmGRX-my_898GE,4116
|
|
3
3
|
sayou/visualizer/core/exceptions.py,sha256=Mk5UtIfim7i9688c4qAKP7kB1GpLPM29t94HbQM9fhw,99
|
|
4
4
|
sayou/visualizer/core/schemas.py,sha256=qn44BINevFZF_ALBhh20DS4GyMo5HV3UzqY4UTh_p3A,381
|
|
5
|
+
sayou/visualizer/core/styles.py,sha256=ZyMqzu9Xk-TY1xpkHeGZb0qkElG7MyHyYEpqFWXig2U,6285
|
|
5
6
|
sayou/visualizer/interfaces/base_renderer.py,sha256=orllTXlqM4-wDemOWbcZX8zF708KOdWFgoqZh8MeAzE,760
|
|
6
|
-
sayou/visualizer/renderer/analytic_kg_renderer.py,sha256=
|
|
7
|
+
sayou/visualizer/renderer/analytic_kg_renderer.py,sha256=5lNhllAe4WLf3-vc_Gg1DEpRbKWGCFBEvAwZGpncRWU,11246
|
|
7
8
|
sayou/visualizer/renderer/pyvis_renderer.py,sha256=2HKv_qAKKNHMKLwC7xoIn3EZ5oFLpgds7LPgK4EeXfA,2408
|
|
8
|
-
sayou/visualizer/renderer/showcase_kg_renderer.py,sha256=
|
|
9
|
+
sayou/visualizer/renderer/showcase_kg_renderer.py,sha256=P1OoKOsmAJFdP1weWWOD6EIINY_prfB135j5PFQ9a4E,11489
|
|
9
10
|
sayou/visualizer/tracer/graph_tracer.py,sha256=j0dqd0_67ZnQCNjn5siKHXXsXasWim9olYqUQA2jKxk,3638
|
|
10
11
|
sayou/visualizer/tracer/rich_tracer.py,sha256=ik7J1P7AMTN47lkjMLE7iTlRuksUpwSKluvWdpY6kdQ,2406
|
|
11
12
|
sayou/visualizer/tracer/websocket_tracer.py,sha256=OZLg4jTfuxp6IwDacmAACKZ_0FirZFhyLysqh9QyrJA,1626
|
|
12
|
-
sayou_visualizer-0.0.
|
|
13
|
-
sayou_visualizer-0.0.
|
|
14
|
-
sayou_visualizer-0.0.
|
|
13
|
+
sayou_visualizer-0.0.12.dist-info/METADATA,sha256=l6O1MyvZrMebDZ5OGY9wbEJSVj2B7gUCiz_0wOVzTXA,16681
|
|
14
|
+
sayou_visualizer-0.0.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
15
|
+
sayou_visualizer-0.0.12.dist-info/RECORD,,
|
|
File without changes
|