@matdata/yasgui-graph-plugin 1.0.2 → 1.0.3
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.
- package/LICENSE +201 -201
- package/README.md +301 -301
- package/dist/yasgui-graph-plugin.cjs.js +399 -0
- package/dist/yasgui-graph-plugin.cjs.js.map +7 -0
- package/dist/yasgui-graph-plugin.esm.js +377 -0
- package/dist/yasgui-graph-plugin.esm.js.map +7 -0
- package/dist/yasgui-graph-plugin.min.js +2 -0
- package/dist/yasgui-graph-plugin.min.js.map +7 -0
- package/package.json +48 -52
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
// src/prefixUtils.js
|
|
2
|
+
function extractPrefixes(yasrResults) {
|
|
3
|
+
const prefixMap = /* @__PURE__ */ new Map();
|
|
4
|
+
if (yasrResults && yasrResults.getVariables) {
|
|
5
|
+
const vars = yasrResults.getVariables();
|
|
6
|
+
if (vars && vars.prefixes) {
|
|
7
|
+
Object.entries(vars.prefixes).forEach(([prefix, uri]) => {
|
|
8
|
+
prefixMap.set(uri, prefix);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const commonPrefixes = {
|
|
13
|
+
"http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
|
|
14
|
+
"http://www.w3.org/2000/01/rdf-schema#": "rdfs",
|
|
15
|
+
"http://www.w3.org/2001/XMLSchema#": "xsd",
|
|
16
|
+
"http://www.w3.org/2002/07/owl#": "owl"
|
|
17
|
+
};
|
|
18
|
+
Object.entries(commonPrefixes).forEach(([uri, prefix]) => {
|
|
19
|
+
if (!prefixMap.has(uri)) {
|
|
20
|
+
prefixMap.set(uri, prefix);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return prefixMap;
|
|
24
|
+
}
|
|
25
|
+
function applyPrefix(uri, prefixMap) {
|
|
26
|
+
if (!uri || typeof uri !== "string")
|
|
27
|
+
return uri;
|
|
28
|
+
for (const [namespace, prefix] of prefixMap.entries()) {
|
|
29
|
+
if (uri.startsWith(namespace)) {
|
|
30
|
+
const localName = uri.substring(namespace.length);
|
|
31
|
+
return `${prefix}:${localName}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return uri;
|
|
35
|
+
}
|
|
36
|
+
function truncateLabel(text, maxLength = 50) {
|
|
37
|
+
if (!text || typeof text !== "string")
|
|
38
|
+
return text;
|
|
39
|
+
if (text.length <= maxLength)
|
|
40
|
+
return text;
|
|
41
|
+
return text.substring(0, maxLength - 3) + "...";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/networkConfig.js
|
|
45
|
+
function getDefaultNetworkOptions() {
|
|
46
|
+
return {
|
|
47
|
+
autoResize: true,
|
|
48
|
+
width: "100%",
|
|
49
|
+
height: "100%",
|
|
50
|
+
physics: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
stabilization: {
|
|
53
|
+
enabled: true,
|
|
54
|
+
iterations: 200,
|
|
55
|
+
// Max iterations for performance (<2s target)
|
|
56
|
+
updateInterval: 25
|
|
57
|
+
},
|
|
58
|
+
barnesHut: {
|
|
59
|
+
gravitationalConstant: -2e3,
|
|
60
|
+
centralGravity: 0.3,
|
|
61
|
+
springLength: 95,
|
|
62
|
+
springConstant: 0.04,
|
|
63
|
+
damping: 0.09
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
interaction: {
|
|
67
|
+
dragNodes: true,
|
|
68
|
+
dragView: true,
|
|
69
|
+
zoomView: true,
|
|
70
|
+
hover: true,
|
|
71
|
+
tooltipDelay: 300
|
|
72
|
+
// 300ms hover delay per spec
|
|
73
|
+
},
|
|
74
|
+
nodes: {
|
|
75
|
+
shape: "dot",
|
|
76
|
+
size: 20,
|
|
77
|
+
font: {
|
|
78
|
+
size: 14,
|
|
79
|
+
color: "#000000",
|
|
80
|
+
align: "center",
|
|
81
|
+
vadjust: 0,
|
|
82
|
+
multi: false
|
|
83
|
+
},
|
|
84
|
+
borderWidth: 2,
|
|
85
|
+
borderWidthSelected: 3,
|
|
86
|
+
labelHighlightBold: true,
|
|
87
|
+
fixed: {
|
|
88
|
+
x: false,
|
|
89
|
+
y: false
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
edges: {
|
|
93
|
+
arrows: {
|
|
94
|
+
to: {
|
|
95
|
+
enabled: true,
|
|
96
|
+
scaleFactor: 0.5
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
smooth: {
|
|
100
|
+
enabled: true,
|
|
101
|
+
type: "dynamic"
|
|
102
|
+
},
|
|
103
|
+
font: {
|
|
104
|
+
size: 12,
|
|
105
|
+
align: "middle"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/parsers.js
|
|
112
|
+
function parseConstructResults(yasrResults) {
|
|
113
|
+
const triples = [];
|
|
114
|
+
if (!yasrResults || !yasrResults.getBindings) {
|
|
115
|
+
return triples;
|
|
116
|
+
}
|
|
117
|
+
const bindings = yasrResults.getBindings();
|
|
118
|
+
bindings.forEach((binding) => {
|
|
119
|
+
if (!binding.subject || !binding.predicate || !binding.object) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const triple = {
|
|
123
|
+
subject: binding.subject.value,
|
|
124
|
+
predicate: binding.predicate.value,
|
|
125
|
+
object: {
|
|
126
|
+
value: binding.object.value,
|
|
127
|
+
type: binding.object.type || "uri",
|
|
128
|
+
datatype: binding.object.datatype,
|
|
129
|
+
lang: binding.object["xml:lang"]
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
triples.push(triple);
|
|
133
|
+
});
|
|
134
|
+
return triples;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/colorUtils.js
|
|
138
|
+
function getNodeColor(node, triples) {
|
|
139
|
+
if (node.uri && node.uri.startsWith("_:")) {
|
|
140
|
+
return "#c5c5c5ff";
|
|
141
|
+
}
|
|
142
|
+
if (node.type === "literal") {
|
|
143
|
+
return "#a6c8a6ff";
|
|
144
|
+
}
|
|
145
|
+
const isTypeObject = triples.some(
|
|
146
|
+
(triple) => triple.predicate === "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" && triple.object.value === node.uri
|
|
147
|
+
);
|
|
148
|
+
if (isTypeObject) {
|
|
149
|
+
return "#e15b13ff";
|
|
150
|
+
}
|
|
151
|
+
return "#97C2FC";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/transformers.js
|
|
155
|
+
function createNodeMap(triples, prefixMap) {
|
|
156
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
157
|
+
let nodeId = 1;
|
|
158
|
+
triples.forEach((triple) => {
|
|
159
|
+
if (!nodeMap.has(triple.subject)) {
|
|
160
|
+
const isBlankNode = triple.subject.startsWith("_:");
|
|
161
|
+
const label = isBlankNode ? triple.subject : truncateLabel(applyPrefix(triple.subject, prefixMap));
|
|
162
|
+
nodeMap.set(triple.subject, {
|
|
163
|
+
id: nodeId++,
|
|
164
|
+
uri: triple.subject,
|
|
165
|
+
label,
|
|
166
|
+
color: getNodeColor({ uri: triple.subject, type: "uri" }, triples),
|
|
167
|
+
type: "uri",
|
|
168
|
+
fullValue: triple.subject,
|
|
169
|
+
title: isBlankNode ? triple.subject : applyPrefix(triple.subject, prefixMap),
|
|
170
|
+
font: {
|
|
171
|
+
vadjust: -30,
|
|
172
|
+
// Position label above the node
|
|
173
|
+
align: "center"
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
const objValue = triple.object.value;
|
|
178
|
+
if (!nodeMap.has(objValue)) {
|
|
179
|
+
const isLiteral = triple.object.type === "literal";
|
|
180
|
+
const isBlankNode = !isLiteral && objValue.startsWith("_:");
|
|
181
|
+
let label, fullValue, title;
|
|
182
|
+
if (isLiteral) {
|
|
183
|
+
label = truncateLabel(objValue);
|
|
184
|
+
fullValue = objValue;
|
|
185
|
+
title = triple.object.datatype ? `"${objValue}"^^${applyPrefix(triple.object.datatype, prefixMap)}` : `"${objValue}"`;
|
|
186
|
+
} else if (isBlankNode) {
|
|
187
|
+
label = objValue;
|
|
188
|
+
fullValue = objValue;
|
|
189
|
+
title = objValue;
|
|
190
|
+
} else {
|
|
191
|
+
label = truncateLabel(applyPrefix(objValue, prefixMap));
|
|
192
|
+
fullValue = objValue;
|
|
193
|
+
title = applyPrefix(objValue, prefixMap);
|
|
194
|
+
}
|
|
195
|
+
nodeMap.set(objValue, {
|
|
196
|
+
id: nodeId++,
|
|
197
|
+
uri: isLiteral ? null : objValue,
|
|
198
|
+
label,
|
|
199
|
+
color: getNodeColor(
|
|
200
|
+
{ uri: objValue, type: isLiteral ? "literal" : "uri" },
|
|
201
|
+
triples
|
|
202
|
+
),
|
|
203
|
+
type: isLiteral ? "literal" : "uri",
|
|
204
|
+
fullValue,
|
|
205
|
+
title,
|
|
206
|
+
font: {
|
|
207
|
+
vadjust: -30,
|
|
208
|
+
// Position label above the node
|
|
209
|
+
align: "center"
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
return nodeMap;
|
|
215
|
+
}
|
|
216
|
+
function createEdgesArray(triples, nodeMap, prefixMap) {
|
|
217
|
+
const edges = [];
|
|
218
|
+
const edgeSet = /* @__PURE__ */ new Set();
|
|
219
|
+
triples.forEach((triple) => {
|
|
220
|
+
const fromNode = nodeMap.get(triple.subject);
|
|
221
|
+
const toNode = nodeMap.get(triple.object.value);
|
|
222
|
+
if (!fromNode || !toNode)
|
|
223
|
+
return;
|
|
224
|
+
const edgeKey = `${fromNode.id}-${triple.predicate}-${toNode.id}`;
|
|
225
|
+
if (!edgeSet.has(edgeKey)) {
|
|
226
|
+
edgeSet.add(edgeKey);
|
|
227
|
+
edges.push({
|
|
228
|
+
id: `edge_${fromNode.id}_${toNode.id}_${edges.length}`,
|
|
229
|
+
from: fromNode.id,
|
|
230
|
+
to: toNode.id,
|
|
231
|
+
label: truncateLabel(applyPrefix(triple.predicate, prefixMap)),
|
|
232
|
+
predicate: triple.predicate,
|
|
233
|
+
title: applyPrefix(triple.predicate, prefixMap),
|
|
234
|
+
arrows: "to"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
return edges;
|
|
239
|
+
}
|
|
240
|
+
function triplesToGraph(triples, prefixMap) {
|
|
241
|
+
const nodeMap = createNodeMap(triples, prefixMap);
|
|
242
|
+
const edges = createEdgesArray(triples, nodeMap, prefixMap);
|
|
243
|
+
const nodes = Array.from(nodeMap.values());
|
|
244
|
+
return { nodes, edges };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/GraphPlugin.js
|
|
248
|
+
function getVisNetwork() {
|
|
249
|
+
if (typeof window !== "undefined" && window.vis) {
|
|
250
|
+
return window.vis;
|
|
251
|
+
}
|
|
252
|
+
throw new Error("vis-network not found. Load vis-network before GraphPlugin in dev mode.");
|
|
253
|
+
}
|
|
254
|
+
var GraphPlugin = class {
|
|
255
|
+
constructor(yasr) {
|
|
256
|
+
this.yasr = yasr;
|
|
257
|
+
this.network = null;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Plugin priority (higher = shown first in tabs)
|
|
261
|
+
*/
|
|
262
|
+
static get priority() {
|
|
263
|
+
return 20;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Plugin label for tab display
|
|
267
|
+
*/
|
|
268
|
+
static get label() {
|
|
269
|
+
return "Graph";
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Check if plugin can handle the current results
|
|
273
|
+
* @returns {boolean} True if results are from CONSTRUCT or DESCRIBE query
|
|
274
|
+
*/
|
|
275
|
+
canHandleResults() {
|
|
276
|
+
if (!this.yasr || !this.yasr.results)
|
|
277
|
+
return false;
|
|
278
|
+
const results = this.yasr.results;
|
|
279
|
+
if (results.getBindings && typeof results.getBindings === "function") {
|
|
280
|
+
const bindings = results.getBindings();
|
|
281
|
+
if (bindings && bindings.length > 0) {
|
|
282
|
+
const firstBinding = bindings[0];
|
|
283
|
+
return firstBinding.subject !== void 0 && firstBinding.predicate !== void 0 && firstBinding.object !== void 0;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Render the graph visualization
|
|
290
|
+
*/
|
|
291
|
+
draw() {
|
|
292
|
+
this.yasr.resultsEl.innerHTML = "";
|
|
293
|
+
try {
|
|
294
|
+
const triples = parseConstructResults(this.yasr.results);
|
|
295
|
+
if (!triples || triples.length === 0) {
|
|
296
|
+
this.yasr.resultsEl.innerHTML = '<div style="padding: 20px; text-align: center; color: #666;">No graph data to visualize</div>';
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const prefixMap = extractPrefixes(this.yasr.results);
|
|
300
|
+
const { nodes, edges } = triplesToGraph(triples, prefixMap);
|
|
301
|
+
const container = document.createElement("div");
|
|
302
|
+
container.style.width = "100%";
|
|
303
|
+
container.style.height = "600px";
|
|
304
|
+
container.style.position = "relative";
|
|
305
|
+
container.style.overflow = "hidden";
|
|
306
|
+
this.yasr.resultsEl.appendChild(container);
|
|
307
|
+
const { Network, DataSet } = getVisNetwork();
|
|
308
|
+
const nodesDataSet = new DataSet(nodes);
|
|
309
|
+
const edgesDataSet = new DataSet(edges);
|
|
310
|
+
const options = getDefaultNetworkOptions();
|
|
311
|
+
this.network = new Network(
|
|
312
|
+
container,
|
|
313
|
+
{ nodes: nodesDataSet, edges: edgesDataSet },
|
|
314
|
+
options
|
|
315
|
+
);
|
|
316
|
+
this.networkReady = false;
|
|
317
|
+
this.network.on("stabilizationIterationsDone", () => {
|
|
318
|
+
this.network.setOptions({ physics: { enabled: true } });
|
|
319
|
+
this.networkReady = true;
|
|
320
|
+
});
|
|
321
|
+
const controls = document.createElement("div");
|
|
322
|
+
controls.style.position = "absolute";
|
|
323
|
+
controls.style.top = "10px";
|
|
324
|
+
controls.style.right = "10px";
|
|
325
|
+
controls.style.zIndex = "10000";
|
|
326
|
+
controls.style.display = "flex";
|
|
327
|
+
controls.style.gap = "10px";
|
|
328
|
+
controls.style.pointerEvents = "auto";
|
|
329
|
+
container.appendChild(controls);
|
|
330
|
+
const fitButton = document.createElement("button");
|
|
331
|
+
fitButton.textContent = "Zoom to Fit";
|
|
332
|
+
fitButton.style.padding = "8px 12px";
|
|
333
|
+
fitButton.style.background = "#4CAF50";
|
|
334
|
+
fitButton.style.color = "white";
|
|
335
|
+
fitButton.style.border = "none";
|
|
336
|
+
fitButton.style.borderRadius = "4px";
|
|
337
|
+
fitButton.style.cursor = "pointer";
|
|
338
|
+
fitButton.style.fontSize = "14px";
|
|
339
|
+
fitButton.style.boxShadow = "0 2px 4px rgba(0,0,0,0.2)";
|
|
340
|
+
fitButton.onmouseover = () => fitButton.style.background = "#45a049";
|
|
341
|
+
fitButton.onmouseout = () => fitButton.style.background = "#4CAF50";
|
|
342
|
+
fitButton.onclick = () => {
|
|
343
|
+
if (this.network) {
|
|
344
|
+
this.network.fit({ animation: { duration: 300, easingFunction: "easeInOutQuad" } });
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
controls.appendChild(fitButton);
|
|
348
|
+
if (triples.length > 1e3) {
|
|
349
|
+
console.warn("Large graph detected (>1000 triples). Rendering may be slow.");
|
|
350
|
+
}
|
|
351
|
+
} catch (error) {
|
|
352
|
+
console.error("Error rendering graph:", error);
|
|
353
|
+
this.yasr.resultsEl.innerHTML = '<div style="padding: 20px; color: red;">Error rendering graph. See console for details.</div>';
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get icon for plugin tab
|
|
358
|
+
* @returns {Element} Icon element
|
|
359
|
+
*/
|
|
360
|
+
getIcon() {
|
|
361
|
+
const icon = document.createElement("span");
|
|
362
|
+
icon.className = "fas fa-project-diagram";
|
|
363
|
+
icon.setAttribute("aria-label", "Graph visualization");
|
|
364
|
+
return icon;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
var GraphPlugin_default = GraphPlugin;
|
|
368
|
+
|
|
369
|
+
// src/index.js
|
|
370
|
+
if (typeof window !== "undefined" && window.Yasgui && window.Yasgui.Yasr) {
|
|
371
|
+
window.Yasgui.Yasr.registerPlugin("Graph", GraphPlugin_default);
|
|
372
|
+
}
|
|
373
|
+
var src_default = GraphPlugin_default;
|
|
374
|
+
export {
|
|
375
|
+
src_default as default
|
|
376
|
+
};
|
|
377
|
+
//# sourceMappingURL=yasgui-graph-plugin.esm.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/prefixUtils.js", "../src/networkConfig.js", "../src/parsers.js", "../src/colorUtils.js", "../src/transformers.js", "../src/GraphPlugin.js", "../src/index.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * Extract namespace prefixes from SPARQL results metadata\r\n * @param {Object} yasrResults - YASR results object\r\n * @returns {Map<string, string>} Map of namespace URI to prefix\r\n */\r\nfunction extractPrefixes(yasrResults) {\r\n const prefixMap = new Map();\r\n \r\n // Check for prefixes in results metadata\r\n if (yasrResults && yasrResults.getVariables) {\r\n const vars = yasrResults.getVariables();\r\n if (vars && vars.prefixes) {\r\n Object.entries(vars.prefixes).forEach(([prefix, uri]) => {\r\n prefixMap.set(uri, prefix);\r\n });\r\n }\r\n }\r\n \r\n // Add common RDF prefixes as fallback\r\n const commonPrefixes = {\r\n 'http://www.w3.org/1999/02/22-rdf-syntax-ns#': 'rdf',\r\n 'http://www.w3.org/2000/01/rdf-schema#': 'rdfs',\r\n 'http://www.w3.org/2001/XMLSchema#': 'xsd',\r\n 'http://www.w3.org/2002/07/owl#': 'owl',\r\n };\r\n \r\n Object.entries(commonPrefixes).forEach(([uri, prefix]) => {\r\n if (!prefixMap.has(uri)) {\r\n prefixMap.set(uri, prefix);\r\n }\r\n });\r\n \r\n return prefixMap;\r\n}\r\n\r\n/**\r\n * Convert full URI to prefixed form\r\n * @param {string} uri - Full URI\r\n * @param {Map<string, string>} prefixMap - Namespace to prefix mappings\r\n * @returns {string} Prefixed URI (e.g., \"ex:Person\") or original if no match\r\n */\r\nfunction applyPrefix(uri, prefixMap) {\r\n if (!uri || typeof uri !== 'string') return uri;\r\n \r\n for (const [namespace, prefix] of prefixMap.entries()) {\r\n if (uri.startsWith(namespace)) {\r\n const localName = uri.substring(namespace.length);\r\n return `${prefix}:${localName}`;\r\n }\r\n }\r\n \r\n return uri;\r\n}\r\n\r\n/**\r\n * Truncate long labels with ellipsis\r\n * @param {string} text - Text to truncate\r\n * @param {number} maxLength - Maximum length before truncation (default: 50)\r\n * @returns {string} Truncated text with ellipsis if needed\r\n */\r\nfunction truncateLabel(text, maxLength = 50) {\r\n if (!text || typeof text !== 'string') return text;\r\n \r\n if (text.length <= maxLength) return text;\r\n \r\n return text.substring(0, maxLength - 3) + '...';\r\n}\r\n\r\nexport {\r\n extractPrefixes,\r\n applyPrefix,\r\n truncateLabel,\r\n};\r\n", "/**\r\n * Get default vis-network configuration options\r\n * @returns {Object} vis-network options object\r\n */\r\nfunction getDefaultNetworkOptions() {\r\n return {\r\n autoResize: true,\r\n width: '100%',\r\n height: '100%',\r\n \r\n physics: {\r\n enabled: true,\r\n stabilization: {\r\n enabled: true,\r\n iterations: 200, // Max iterations for performance (<2s target)\r\n updateInterval: 25,\r\n },\r\n barnesHut: {\r\n gravitationalConstant: -2000,\r\n centralGravity: 0.3,\r\n springLength: 95,\r\n springConstant: 0.04,\r\n damping: 0.09,\r\n },\r\n },\r\n \r\n interaction: {\r\n dragNodes: true,\r\n dragView: true,\r\n zoomView: true,\r\n hover: true,\r\n tooltipDelay: 300, // 300ms hover delay per spec\r\n },\r\n \r\n nodes: {\r\n shape: 'dot',\r\n size: 20,\r\n font: {\r\n size: 14,\r\n color: '#000000',\r\n align: 'center',\r\n vadjust: 0,\r\n multi: false,\r\n },\r\n borderWidth: 2,\r\n borderWidthSelected: 3,\r\n labelHighlightBold: true,\r\n fixed: {\r\n x: false,\r\n y: false,\r\n },\r\n },\r\n \r\n edges: {\r\n arrows: {\r\n to: {\r\n enabled: true,\r\n scaleFactor: 0.5,\r\n },\r\n },\r\n smooth: {\r\n enabled: true,\r\n type: 'dynamic',\r\n },\r\n font: {\r\n size: 12,\r\n align: 'middle',\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport {\r\n getDefaultNetworkOptions,\r\n};\r\n", "/**\r\n * Parse SPARQL CONSTRUCT results to extract RDF triples\r\n * @param {Object} yasrResults - YASR results object\r\n * @returns {Array<Object>} Array of RDFTriple objects {subject, predicate, object}\r\n */\r\nfunction parseConstructResults(yasrResults) {\r\n const triples = [];\r\n \r\n if (!yasrResults || !yasrResults.getBindings) {\r\n return triples;\r\n }\r\n \r\n const bindings = yasrResults.getBindings();\r\n \r\n bindings.forEach((binding) => {\r\n if (!binding.subject || !binding.predicate || !binding.object) {\r\n return; // Skip incomplete bindings\r\n }\r\n \r\n const triple = {\r\n subject: binding.subject.value,\r\n predicate: binding.predicate.value,\r\n object: {\r\n value: binding.object.value,\r\n type: binding.object.type || 'uri',\r\n datatype: binding.object.datatype,\r\n lang: binding.object['xml:lang'],\r\n },\r\n };\r\n \r\n triples.push(triple);\r\n });\r\n \r\n return triples;\r\n}\r\n\r\nexport {\r\n parseConstructResults,\r\n};\r\n", "/**\r\n * Determine node color based on type and predicates\r\n * @param {Object} node - Node object with uri, type properties\r\n * @param {Array} triples - All RDF triples for context\r\n * @returns {string} Hex color code\r\n */\r\nfunction getNodeColor(node, triples) {\r\n // Blank nodes: light grey\r\n if (node.uri && node.uri.startsWith('_:')) {\r\n return '#c5c5c5ff';\r\n }\r\n \r\n // Literals: light green\r\n if (node.type === 'literal') {\r\n return '#a6c8a6ff';\r\n }\r\n \r\n // Check if node is object of rdf:type predicate: orange\r\n const isTypeObject = triples.some(\r\n (triple) =>\r\n triple.predicate === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' &&\r\n triple.object.value === node.uri\r\n );\r\n \r\n if (isTypeObject) {\r\n return '#e15b13ff';\r\n }\r\n \r\n // Other URIs: light blue\r\n return '#97C2FC';\r\n}\r\n\r\nexport {\r\n getNodeColor,\r\n};\r\n", "import { applyPrefix, truncateLabel } from './prefixUtils.js';\r\nimport { getNodeColor } from './colorUtils.js';\r\n\r\n/**\r\n * Create deduplicated node map from triples\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Map<string, Object>} Map of node value to GraphNode\r\n */\r\nfunction createNodeMap(triples, prefixMap) {\r\n const nodeMap = new Map();\r\n let nodeId = 1;\r\n \r\n triples.forEach((triple) => {\r\n // Add subject node\r\n if (!nodeMap.has(triple.subject)) {\r\n const isBlankNode = triple.subject.startsWith('_:');\r\n const label = isBlankNode\r\n ? triple.subject\r\n : truncateLabel(applyPrefix(triple.subject, prefixMap));\r\n \r\n nodeMap.set(triple.subject, {\r\n id: nodeId++,\r\n uri: triple.subject,\r\n label: label,\r\n color: getNodeColor({ uri: triple.subject, type: 'uri' }, triples),\r\n type: 'uri',\r\n fullValue: triple.subject,\r\n title: isBlankNode ? triple.subject : applyPrefix(triple.subject, prefixMap),\r\n font: {\r\n vadjust: -30, // Position label above the node\r\n align: 'center',\r\n },\r\n });\r\n }\r\n \r\n // Add object node\r\n const objValue = triple.object.value;\r\n if (!nodeMap.has(objValue)) {\r\n const isLiteral = triple.object.type === 'literal';\r\n const isBlankNode = !isLiteral && objValue.startsWith('_:');\r\n \r\n let label, fullValue, title;\r\n \r\n if (isLiteral) {\r\n label = truncateLabel(objValue);\r\n fullValue = objValue;\r\n title = triple.object.datatype\r\n ? `\"${objValue}\"^^${applyPrefix(triple.object.datatype, prefixMap)}`\r\n : `\"${objValue}\"`;\r\n } else if (isBlankNode) {\r\n label = objValue;\r\n fullValue = objValue;\r\n title = objValue;\r\n } else {\r\n label = truncateLabel(applyPrefix(objValue, prefixMap));\r\n fullValue = objValue;\r\n title = applyPrefix(objValue, prefixMap);\r\n }\r\n \r\n nodeMap.set(objValue, {\r\n id: nodeId++,\r\n uri: isLiteral ? null : objValue,\r\n label: label,\r\n color: getNodeColor(\r\n { uri: objValue, type: isLiteral ? 'literal' : 'uri' },\r\n triples\r\n ),\r\n type: isLiteral ? 'literal' : 'uri',\r\n fullValue: fullValue,\r\n title: title,\r\n font: {\r\n vadjust: -30, // Position label above the node\r\n align: 'center',\r\n },\r\n });\r\n }\r\n });\r\n \r\n return nodeMap;\r\n}\r\n\r\n/**\r\n * Create edges array from triples\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} nodeMap - Map of node values to GraphNodes\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Array<Object>} Array of GraphEdge objects\r\n */\r\nfunction createEdgesArray(triples, nodeMap, prefixMap) {\r\n const edges = [];\r\n const edgeSet = new Set(); // For deduplication\r\n \r\n triples.forEach((triple) => {\r\n const fromNode = nodeMap.get(triple.subject);\r\n const toNode = nodeMap.get(triple.object.value);\r\n \r\n if (!fromNode || !toNode) return;\r\n \r\n // Create unique edge identifier for deduplication\r\n const edgeKey = `${fromNode.id}-${triple.predicate}-${toNode.id}`;\r\n \r\n if (!edgeSet.has(edgeKey)) {\r\n edgeSet.add(edgeKey);\r\n \r\n edges.push({\r\n id: `edge_${fromNode.id}_${toNode.id}_${edges.length}`,\r\n from: fromNode.id,\r\n to: toNode.id,\r\n label: truncateLabel(applyPrefix(triple.predicate, prefixMap)),\r\n predicate: triple.predicate,\r\n title: applyPrefix(triple.predicate, prefixMap),\r\n arrows: 'to',\r\n });\r\n }\r\n });\r\n \r\n return edges;\r\n}\r\n\r\n/**\r\n * Transform RDF triples to graph data structure\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Object} {nodes: Array, edges: Array}\r\n */\r\nfunction triplesToGraph(triples, prefixMap) {\r\n const nodeMap = createNodeMap(triples, prefixMap);\r\n const edges = createEdgesArray(triples, nodeMap, prefixMap);\r\n const nodes = Array.from(nodeMap.values());\r\n \r\n return { nodes, edges };\r\n}\r\n\r\nexport {\r\n createNodeMap,\r\n createEdgesArray,\r\n triplesToGraph,\r\n};\r\n", "import { extractPrefixes } from './prefixUtils.js';\r\nimport { getDefaultNetworkOptions } from './networkConfig.js';\r\nimport { parseConstructResults } from './parsers.js';\r\nimport { triplesToGraph } from './transformers.js';\r\n\r\n// Get vis-network (from global in dev mode, or bundled in production)\r\nfunction getVisNetwork() {\r\n if (typeof window !== 'undefined' && window.vis) {\r\n return window.vis;\r\n }\r\n // In production build, this will be bundled\r\n throw new Error('vis-network not found. Load vis-network before GraphPlugin in dev mode.');\r\n}\r\n\r\n/**\r\n * YASR plugin for visualizing SPARQL CONSTRUCT results as graphs\r\n */\r\nclass GraphPlugin {\r\n constructor(yasr) {\r\n this.yasr = yasr;\r\n this.network = null;\r\n }\r\n\r\n /**\r\n * Plugin priority (higher = shown first in tabs)\r\n */\r\n static get priority() {\r\n return 20;\r\n }\r\n\r\n /**\r\n * Plugin label for tab display\r\n */\r\n static get label() {\r\n return 'Graph';\r\n }\r\n\r\n /**\r\n * Check if plugin can handle the current results\r\n * @returns {boolean} True if results are from CONSTRUCT or DESCRIBE query\r\n */\r\n canHandleResults() {\r\n if (!this.yasr || !this.yasr.results) return false;\r\n\r\n const results = this.yasr.results;\r\n \r\n // Check if results have RDF triple structure (subject/predicate/object)\r\n if (results.getBindings && typeof results.getBindings === 'function') {\r\n const bindings = results.getBindings();\r\n if (bindings && bindings.length > 0) {\r\n const firstBinding = bindings[0];\r\n // CONSTRUCT and DESCRIBE results have subject, predicate, object variables\r\n return (\r\n firstBinding.subject !== undefined &&\r\n firstBinding.predicate !== undefined &&\r\n firstBinding.object !== undefined\r\n );\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Render the graph visualization\r\n */\r\n draw() {\r\n // Clear previous content\r\n this.yasr.resultsEl.innerHTML = '';\r\n \r\n try {\r\n // Parse RDF triples from results\r\n const triples = parseConstructResults(this.yasr.results);\r\n \r\n // Handle empty results\r\n if (!triples || triples.length === 0) {\r\n this.yasr.resultsEl.innerHTML = '<div style=\"padding: 20px; text-align: center; color: #666;\">No graph data to visualize</div>';\r\n return;\r\n }\r\n \r\n // Extract prefixes\r\n const prefixMap = extractPrefixes(this.yasr.results);\r\n \r\n // Transform triples to graph data\r\n const { nodes, edges } = triplesToGraph(triples, prefixMap);\r\n \r\n // Create container\r\n const container = document.createElement('div');\r\n container.style.width = '100%';\r\n container.style.height = '600px';\r\n container.style.position = 'relative';\r\n container.style.overflow = 'hidden';\r\n this.yasr.resultsEl.appendChild(container);\r\n \r\n // Get vis-network classes\r\n const { Network, DataSet } = getVisNetwork();\r\n \r\n // Create vis-network DataSets\r\n const nodesDataSet = new DataSet(nodes);\r\n const edgesDataSet = new DataSet(edges);\r\n \r\n // Initialize network\r\n const options = getDefaultNetworkOptions();\r\n this.network = new Network(\r\n container,\r\n { nodes: nodesDataSet, edges: edgesDataSet },\r\n options\r\n );\r\n \r\n // Track network readiness\r\n this.networkReady = false;\r\n \r\n // Disable physics after stabilization (performance optimization)\r\n this.network.on('stabilizationIterationsDone', () => {\r\n this.network.setOptions({ physics: { enabled: true } });\r\n this.networkReady = true;\r\n });\r\n \r\n // Add controls container AFTER network is created\r\n const controls = document.createElement('div');\r\n controls.style.position = 'absolute';\r\n controls.style.top = '10px';\r\n controls.style.right = '10px';\r\n controls.style.zIndex = '10000';\r\n controls.style.display = 'flex';\r\n controls.style.gap = '10px';\r\n controls.style.pointerEvents = 'auto';\r\n container.appendChild(controls);\r\n \r\n // Add \"Zoom to Fit\" button\r\n const fitButton = document.createElement('button');\r\n fitButton.textContent = 'Zoom to Fit';\r\n fitButton.style.padding = '8px 12px';\r\n fitButton.style.background = '#4CAF50';\r\n fitButton.style.color = 'white';\r\n fitButton.style.border = 'none';\r\n fitButton.style.borderRadius = '4px';\r\n fitButton.style.cursor = 'pointer';\r\n fitButton.style.fontSize = '14px';\r\n fitButton.style.boxShadow = '0 2px 4px rgba(0,0,0,0.2)';\r\n fitButton.onmouseover = () => fitButton.style.background = '#45a049';\r\n fitButton.onmouseout = () => fitButton.style.background = '#4CAF50';\r\n fitButton.onclick = () => {\r\n if (this.network) {\r\n this.network.fit({ animation: { duration: 300, easingFunction: 'easeInOutQuad' } });\r\n }\r\n };\r\n controls.appendChild(fitButton);\r\n \r\n // Add performance warning for large graphs\r\n if (triples.length > 1000) {\r\n console.warn('Large graph detected (>1000 triples). Rendering may be slow.');\r\n }\r\n \r\n } catch (error) {\r\n console.error('Error rendering graph:', error);\r\n this.yasr.resultsEl.innerHTML = '<div style=\"padding: 20px; color: red;\">Error rendering graph. See console for details.</div>';\r\n }\r\n }\r\n\r\n /**\r\n * Get icon for plugin tab\r\n * @returns {Element} Icon element\r\n */\r\n getIcon() {\r\n const icon = document.createElement('span');\r\n icon.className = 'fas fa-project-diagram';\r\n icon.setAttribute('aria-label', 'Graph visualization');\r\n return icon;\r\n }\r\n}\r\n\r\nexport default GraphPlugin;\r\n", "import GraphPlugin from './GraphPlugin.js';\r\n\r\n// Auto-register plugin if Yasgui is available (UMD global)\r\nif (typeof window !== 'undefined' && window.Yasgui && window.Yasgui.Yasr) {\r\n window.Yasgui.Yasr.registerPlugin('Graph', GraphPlugin);\r\n}\r\n\r\nexport default GraphPlugin;\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var GraphPlugin=(()=>{var h=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var C=(t,e)=>{for(var n in e)h(t,n,{get:e[n],enumerable:!0})},z=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of E(e))!N.call(t,o)&&o!==n&&h(t,o,{get:()=>e[o],enumerable:!(r=k(e,o))||r.enumerable});return t};var $=t=>z(h({},"__esModule",{value:!0}),t);var O={};C(O,{default:()=>V});function m(t){let e=new Map;if(t&&t.getVariables){let r=t.getVariables();r&&r.prefixes&&Object.entries(r.prefixes).forEach(([o,s])=>{e.set(s,o)})}return Object.entries({"http://www.w3.org/1999/02/22-rdf-syntax-ns#":"rdf","http://www.w3.org/2000/01/rdf-schema#":"rdfs","http://www.w3.org/2001/XMLSchema#":"xsd","http://www.w3.org/2002/07/owl#":"owl"}).forEach(([r,o])=>{e.has(r)||e.set(r,o)}),e}function u(t,e){if(!t||typeof t!="string")return t;for(let[n,r]of e.entries())if(t.startsWith(n)){let o=t.substring(n.length);return`${r}:${o}`}return t}function g(t,e=50){return!t||typeof t!="string"||t.length<=e?t:t.substring(0,e-3)+"..."}function j(){return{autoResize:!0,width:"100%",height:"100%",physics:{enabled:!0,stabilization:{enabled:!0,iterations:200,updateInterval:25},barnesHut:{gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09}},interaction:{dragNodes:!0,dragView:!0,zoomView:!0,hover:!0,tooltipDelay:300},nodes:{shape:"dot",size:20,font:{size:14,color:"#000000",align:"center",vadjust:0,multi:!1},borderWidth:2,borderWidthSelected:3,labelHighlightBold:!0,fixed:{x:!1,y:!1}},edges:{arrows:{to:{enabled:!0,scaleFactor:.5}},smooth:{enabled:!0,type:"dynamic"},font:{size:12,align:"middle"}}}}function v(t){let e=[];return!t||!t.getBindings||t.getBindings().forEach(r=>{if(!r.subject||!r.predicate||!r.object)return;let o={subject:r.subject.value,predicate:r.predicate.value,object:{value:r.object.value,type:r.object.type||"uri",datatype:r.object.datatype,lang:r.object["xml:lang"]}};e.push(o)}),e}function w(t,e){return t.uri&&t.uri.startsWith("_:")?"#c5c5c5ff":t.type==="literal"?"#a6c8a6ff":e.some(r=>r.predicate==="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"&&r.object.value===t.uri)?"#e15b13ff":"#97C2FC"}function B(t,e){let n=new Map,r=1;return t.forEach(o=>{if(!n.has(o.subject)){let i=o.subject.startsWith("_:"),c=i?o.subject:g(u(o.subject,e));n.set(o.subject,{id:r++,uri:o.subject,label:c,color:w({uri:o.subject,type:"uri"},t),type:"uri",fullValue:o.subject,title:i?o.subject:u(o.subject,e),font:{vadjust:-30,align:"center"}})}let s=o.object.value;if(!n.has(s)){let i=o.object.type==="literal",c=!i&&s.startsWith("_:"),l,f,p;i?(l=g(s),f=s,p=o.object.datatype?`"${s}"^^${u(o.object.datatype,e)}`:`"${s}"`):c?(l=s,f=s,p=s):(l=g(u(s,e)),f=s,p=u(s,e)),n.set(s,{id:r++,uri:i?null:s,label:l,color:w({uri:s,type:i?"literal":"uri"},t),type:i?"literal":"uri",fullValue:f,title:p,font:{vadjust:-30,align:"center"}})}}),n}function S(t,e,n){let r=[],o=new Set;return t.forEach(s=>{let i=e.get(s.subject),c=e.get(s.object.value);if(!i||!c)return;let l=`${i.id}-${s.predicate}-${c.id}`;o.has(l)||(o.add(l),r.push({id:`edge_${i.id}_${c.id}_${r.length}`,from:i.id,to:c.id,label:g(u(s.predicate,n)),predicate:s.predicate,title:u(s.predicate,n),arrows:"to"}))}),r}function x(t,e){let n=B(t,e),r=S(t,n,e);return{nodes:Array.from(n.values()),edges:r}}function L(){if(typeof window!="undefined"&&window.vis)return window.vis;throw new Error("vis-network not found. Load vis-network before GraphPlugin in dev mode.")}var y=class{constructor(e){this.yasr=e,this.network=null}static get priority(){return 20}static get label(){return"Graph"}canHandleResults(){if(!this.yasr||!this.yasr.results)return!1;let e=this.yasr.results;if(e.getBindings&&typeof e.getBindings=="function"){let n=e.getBindings();if(n&&n.length>0){let r=n[0];return r.subject!==void 0&&r.predicate!==void 0&&r.object!==void 0}}return!1}draw(){this.yasr.resultsEl.innerHTML="";try{let e=v(this.yasr.results);if(!e||e.length===0){this.yasr.resultsEl.innerHTML='<div style="padding: 20px; text-align: center; color: #666;">No graph data to visualize</div>';return}let n=m(this.yasr.results),{nodes:r,edges:o}=x(e,n),s=document.createElement("div");s.style.width="100%",s.style.height="600px",s.style.position="relative",s.style.overflow="hidden",this.yasr.resultsEl.appendChild(s);let{Network:i,DataSet:c}=L(),l=new c(r),f=new c(o),p=j();this.network=new i(s,{nodes:l,edges:f},p),this.networkReady=!1,this.network.on("stabilizationIterationsDone",()=>{this.network.setOptions({physics:{enabled:!0}}),this.networkReady=!0});let d=document.createElement("div");d.style.position="absolute",d.style.top="10px",d.style.right="10px",d.style.zIndex="10000",d.style.display="flex",d.style.gap="10px",d.style.pointerEvents="auto",s.appendChild(d);let a=document.createElement("button");a.textContent="Zoom to Fit",a.style.padding="8px 12px",a.style.background="#4CAF50",a.style.color="white",a.style.border="none",a.style.borderRadius="4px",a.style.cursor="pointer",a.style.fontSize="14px",a.style.boxShadow="0 2px 4px rgba(0,0,0,0.2)",a.onmouseover=()=>a.style.background="#45a049",a.onmouseout=()=>a.style.background="#4CAF50",a.onclick=()=>{this.network&&this.network.fit({animation:{duration:300,easingFunction:"easeInOutQuad"}})},d.appendChild(a),e.length>1e3&&console.warn("Large graph detected (>1000 triples). Rendering may be slow.")}catch(e){console.error("Error rendering graph:",e),this.yasr.resultsEl.innerHTML='<div style="padding: 20px; color: red;">Error rendering graph. See console for details.</div>'}}getIcon(){let e=document.createElement("span");return e.className="fas fa-project-diagram",e.setAttribute("aria-label","Graph visualization"),e}},b=y;typeof window!="undefined"&&window.Yasgui&&window.Yasgui.Yasr&&window.Yasgui.Yasr.registerPlugin("Graph",b);var V=b;return $(O);})();
|
|
2
|
+
//# sourceMappingURL=yasgui-graph-plugin.min.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js", "../src/prefixUtils.js", "../src/networkConfig.js", "../src/parsers.js", "../src/colorUtils.js", "../src/transformers.js", "../src/GraphPlugin.js"],
|
|
4
|
+
"sourcesContent": ["import GraphPlugin from './GraphPlugin.js';\r\n\r\n// Auto-register plugin if Yasgui is available (UMD global)\r\nif (typeof window !== 'undefined' && window.Yasgui && window.Yasgui.Yasr) {\r\n window.Yasgui.Yasr.registerPlugin('Graph', GraphPlugin);\r\n}\r\n\r\nexport default GraphPlugin;\r\n", "/**\r\n * Extract namespace prefixes from SPARQL results metadata\r\n * @param {Object} yasrResults - YASR results object\r\n * @returns {Map<string, string>} Map of namespace URI to prefix\r\n */\r\nfunction extractPrefixes(yasrResults) {\r\n const prefixMap = new Map();\r\n \r\n // Check for prefixes in results metadata\r\n if (yasrResults && yasrResults.getVariables) {\r\n const vars = yasrResults.getVariables();\r\n if (vars && vars.prefixes) {\r\n Object.entries(vars.prefixes).forEach(([prefix, uri]) => {\r\n prefixMap.set(uri, prefix);\r\n });\r\n }\r\n }\r\n \r\n // Add common RDF prefixes as fallback\r\n const commonPrefixes = {\r\n 'http://www.w3.org/1999/02/22-rdf-syntax-ns#': 'rdf',\r\n 'http://www.w3.org/2000/01/rdf-schema#': 'rdfs',\r\n 'http://www.w3.org/2001/XMLSchema#': 'xsd',\r\n 'http://www.w3.org/2002/07/owl#': 'owl',\r\n };\r\n \r\n Object.entries(commonPrefixes).forEach(([uri, prefix]) => {\r\n if (!prefixMap.has(uri)) {\r\n prefixMap.set(uri, prefix);\r\n }\r\n });\r\n \r\n return prefixMap;\r\n}\r\n\r\n/**\r\n * Convert full URI to prefixed form\r\n * @param {string} uri - Full URI\r\n * @param {Map<string, string>} prefixMap - Namespace to prefix mappings\r\n * @returns {string} Prefixed URI (e.g., \"ex:Person\") or original if no match\r\n */\r\nfunction applyPrefix(uri, prefixMap) {\r\n if (!uri || typeof uri !== 'string') return uri;\r\n \r\n for (const [namespace, prefix] of prefixMap.entries()) {\r\n if (uri.startsWith(namespace)) {\r\n const localName = uri.substring(namespace.length);\r\n return `${prefix}:${localName}`;\r\n }\r\n }\r\n \r\n return uri;\r\n}\r\n\r\n/**\r\n * Truncate long labels with ellipsis\r\n * @param {string} text - Text to truncate\r\n * @param {number} maxLength - Maximum length before truncation (default: 50)\r\n * @returns {string} Truncated text with ellipsis if needed\r\n */\r\nfunction truncateLabel(text, maxLength = 50) {\r\n if (!text || typeof text !== 'string') return text;\r\n \r\n if (text.length <= maxLength) return text;\r\n \r\n return text.substring(0, maxLength - 3) + '...';\r\n}\r\n\r\nexport {\r\n extractPrefixes,\r\n applyPrefix,\r\n truncateLabel,\r\n};\r\n", "/**\r\n * Get default vis-network configuration options\r\n * @returns {Object} vis-network options object\r\n */\r\nfunction getDefaultNetworkOptions() {\r\n return {\r\n autoResize: true,\r\n width: '100%',\r\n height: '100%',\r\n \r\n physics: {\r\n enabled: true,\r\n stabilization: {\r\n enabled: true,\r\n iterations: 200, // Max iterations for performance (<2s target)\r\n updateInterval: 25,\r\n },\r\n barnesHut: {\r\n gravitationalConstant: -2000,\r\n centralGravity: 0.3,\r\n springLength: 95,\r\n springConstant: 0.04,\r\n damping: 0.09,\r\n },\r\n },\r\n \r\n interaction: {\r\n dragNodes: true,\r\n dragView: true,\r\n zoomView: true,\r\n hover: true,\r\n tooltipDelay: 300, // 300ms hover delay per spec\r\n },\r\n \r\n nodes: {\r\n shape: 'dot',\r\n size: 20,\r\n font: {\r\n size: 14,\r\n color: '#000000',\r\n align: 'center',\r\n vadjust: 0,\r\n multi: false,\r\n },\r\n borderWidth: 2,\r\n borderWidthSelected: 3,\r\n labelHighlightBold: true,\r\n fixed: {\r\n x: false,\r\n y: false,\r\n },\r\n },\r\n \r\n edges: {\r\n arrows: {\r\n to: {\r\n enabled: true,\r\n scaleFactor: 0.5,\r\n },\r\n },\r\n smooth: {\r\n enabled: true,\r\n type: 'dynamic',\r\n },\r\n font: {\r\n size: 12,\r\n align: 'middle',\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport {\r\n getDefaultNetworkOptions,\r\n};\r\n", "/**\r\n * Parse SPARQL CONSTRUCT results to extract RDF triples\r\n * @param {Object} yasrResults - YASR results object\r\n * @returns {Array<Object>} Array of RDFTriple objects {subject, predicate, object}\r\n */\r\nfunction parseConstructResults(yasrResults) {\r\n const triples = [];\r\n \r\n if (!yasrResults || !yasrResults.getBindings) {\r\n return triples;\r\n }\r\n \r\n const bindings = yasrResults.getBindings();\r\n \r\n bindings.forEach((binding) => {\r\n if (!binding.subject || !binding.predicate || !binding.object) {\r\n return; // Skip incomplete bindings\r\n }\r\n \r\n const triple = {\r\n subject: binding.subject.value,\r\n predicate: binding.predicate.value,\r\n object: {\r\n value: binding.object.value,\r\n type: binding.object.type || 'uri',\r\n datatype: binding.object.datatype,\r\n lang: binding.object['xml:lang'],\r\n },\r\n };\r\n \r\n triples.push(triple);\r\n });\r\n \r\n return triples;\r\n}\r\n\r\nexport {\r\n parseConstructResults,\r\n};\r\n", "/**\r\n * Determine node color based on type and predicates\r\n * @param {Object} node - Node object with uri, type properties\r\n * @param {Array} triples - All RDF triples for context\r\n * @returns {string} Hex color code\r\n */\r\nfunction getNodeColor(node, triples) {\r\n // Blank nodes: light grey\r\n if (node.uri && node.uri.startsWith('_:')) {\r\n return '#c5c5c5ff';\r\n }\r\n \r\n // Literals: light green\r\n if (node.type === 'literal') {\r\n return '#a6c8a6ff';\r\n }\r\n \r\n // Check if node is object of rdf:type predicate: orange\r\n const isTypeObject = triples.some(\r\n (triple) =>\r\n triple.predicate === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' &&\r\n triple.object.value === node.uri\r\n );\r\n \r\n if (isTypeObject) {\r\n return '#e15b13ff';\r\n }\r\n \r\n // Other URIs: light blue\r\n return '#97C2FC';\r\n}\r\n\r\nexport {\r\n getNodeColor,\r\n};\r\n", "import { applyPrefix, truncateLabel } from './prefixUtils.js';\r\nimport { getNodeColor } from './colorUtils.js';\r\n\r\n/**\r\n * Create deduplicated node map from triples\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Map<string, Object>} Map of node value to GraphNode\r\n */\r\nfunction createNodeMap(triples, prefixMap) {\r\n const nodeMap = new Map();\r\n let nodeId = 1;\r\n \r\n triples.forEach((triple) => {\r\n // Add subject node\r\n if (!nodeMap.has(triple.subject)) {\r\n const isBlankNode = triple.subject.startsWith('_:');\r\n const label = isBlankNode\r\n ? triple.subject\r\n : truncateLabel(applyPrefix(triple.subject, prefixMap));\r\n \r\n nodeMap.set(triple.subject, {\r\n id: nodeId++,\r\n uri: triple.subject,\r\n label: label,\r\n color: getNodeColor({ uri: triple.subject, type: 'uri' }, triples),\r\n type: 'uri',\r\n fullValue: triple.subject,\r\n title: isBlankNode ? triple.subject : applyPrefix(triple.subject, prefixMap),\r\n font: {\r\n vadjust: -30, // Position label above the node\r\n align: 'center',\r\n },\r\n });\r\n }\r\n \r\n // Add object node\r\n const objValue = triple.object.value;\r\n if (!nodeMap.has(objValue)) {\r\n const isLiteral = triple.object.type === 'literal';\r\n const isBlankNode = !isLiteral && objValue.startsWith('_:');\r\n \r\n let label, fullValue, title;\r\n \r\n if (isLiteral) {\r\n label = truncateLabel(objValue);\r\n fullValue = objValue;\r\n title = triple.object.datatype\r\n ? `\"${objValue}\"^^${applyPrefix(triple.object.datatype, prefixMap)}`\r\n : `\"${objValue}\"`;\r\n } else if (isBlankNode) {\r\n label = objValue;\r\n fullValue = objValue;\r\n title = objValue;\r\n } else {\r\n label = truncateLabel(applyPrefix(objValue, prefixMap));\r\n fullValue = objValue;\r\n title = applyPrefix(objValue, prefixMap);\r\n }\r\n \r\n nodeMap.set(objValue, {\r\n id: nodeId++,\r\n uri: isLiteral ? null : objValue,\r\n label: label,\r\n color: getNodeColor(\r\n { uri: objValue, type: isLiteral ? 'literal' : 'uri' },\r\n triples\r\n ),\r\n type: isLiteral ? 'literal' : 'uri',\r\n fullValue: fullValue,\r\n title: title,\r\n font: {\r\n vadjust: -30, // Position label above the node\r\n align: 'center',\r\n },\r\n });\r\n }\r\n });\r\n \r\n return nodeMap;\r\n}\r\n\r\n/**\r\n * Create edges array from triples\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} nodeMap - Map of node values to GraphNodes\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Array<Object>} Array of GraphEdge objects\r\n */\r\nfunction createEdgesArray(triples, nodeMap, prefixMap) {\r\n const edges = [];\r\n const edgeSet = new Set(); // For deduplication\r\n \r\n triples.forEach((triple) => {\r\n const fromNode = nodeMap.get(triple.subject);\r\n const toNode = nodeMap.get(triple.object.value);\r\n \r\n if (!fromNode || !toNode) return;\r\n \r\n // Create unique edge identifier for deduplication\r\n const edgeKey = `${fromNode.id}-${triple.predicate}-${toNode.id}`;\r\n \r\n if (!edgeSet.has(edgeKey)) {\r\n edgeSet.add(edgeKey);\r\n \r\n edges.push({\r\n id: `edge_${fromNode.id}_${toNode.id}_${edges.length}`,\r\n from: fromNode.id,\r\n to: toNode.id,\r\n label: truncateLabel(applyPrefix(triple.predicate, prefixMap)),\r\n predicate: triple.predicate,\r\n title: applyPrefix(triple.predicate, prefixMap),\r\n arrows: 'to',\r\n });\r\n }\r\n });\r\n \r\n return edges;\r\n}\r\n\r\n/**\r\n * Transform RDF triples to graph data structure\r\n * @param {Array} triples - RDF triples\r\n * @param {Map} prefixMap - Namespace to prefix mappings\r\n * @returns {Object} {nodes: Array, edges: Array}\r\n */\r\nfunction triplesToGraph(triples, prefixMap) {\r\n const nodeMap = createNodeMap(triples, prefixMap);\r\n const edges = createEdgesArray(triples, nodeMap, prefixMap);\r\n const nodes = Array.from(nodeMap.values());\r\n \r\n return { nodes, edges };\r\n}\r\n\r\nexport {\r\n createNodeMap,\r\n createEdgesArray,\r\n triplesToGraph,\r\n};\r\n", "import { extractPrefixes } from './prefixUtils.js';\r\nimport { getDefaultNetworkOptions } from './networkConfig.js';\r\nimport { parseConstructResults } from './parsers.js';\r\nimport { triplesToGraph } from './transformers.js';\r\n\r\n// Get vis-network (from global in dev mode, or bundled in production)\r\nfunction getVisNetwork() {\r\n if (typeof window !== 'undefined' && window.vis) {\r\n return window.vis;\r\n }\r\n // In production build, this will be bundled\r\n throw new Error('vis-network not found. Load vis-network before GraphPlugin in dev mode.');\r\n}\r\n\r\n/**\r\n * YASR plugin for visualizing SPARQL CONSTRUCT results as graphs\r\n */\r\nclass GraphPlugin {\r\n constructor(yasr) {\r\n this.yasr = yasr;\r\n this.network = null;\r\n }\r\n\r\n /**\r\n * Plugin priority (higher = shown first in tabs)\r\n */\r\n static get priority() {\r\n return 20;\r\n }\r\n\r\n /**\r\n * Plugin label for tab display\r\n */\r\n static get label() {\r\n return 'Graph';\r\n }\r\n\r\n /**\r\n * Check if plugin can handle the current results\r\n * @returns {boolean} True if results are from CONSTRUCT or DESCRIBE query\r\n */\r\n canHandleResults() {\r\n if (!this.yasr || !this.yasr.results) return false;\r\n\r\n const results = this.yasr.results;\r\n \r\n // Check if results have RDF triple structure (subject/predicate/object)\r\n if (results.getBindings && typeof results.getBindings === 'function') {\r\n const bindings = results.getBindings();\r\n if (bindings && bindings.length > 0) {\r\n const firstBinding = bindings[0];\r\n // CONSTRUCT and DESCRIBE results have subject, predicate, object variables\r\n return (\r\n firstBinding.subject !== undefined &&\r\n firstBinding.predicate !== undefined &&\r\n firstBinding.object !== undefined\r\n );\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Render the graph visualization\r\n */\r\n draw() {\r\n // Clear previous content\r\n this.yasr.resultsEl.innerHTML = '';\r\n \r\n try {\r\n // Parse RDF triples from results\r\n const triples = parseConstructResults(this.yasr.results);\r\n \r\n // Handle empty results\r\n if (!triples || triples.length === 0) {\r\n this.yasr.resultsEl.innerHTML = '<div style=\"padding: 20px; text-align: center; color: #666;\">No graph data to visualize</div>';\r\n return;\r\n }\r\n \r\n // Extract prefixes\r\n const prefixMap = extractPrefixes(this.yasr.results);\r\n \r\n // Transform triples to graph data\r\n const { nodes, edges } = triplesToGraph(triples, prefixMap);\r\n \r\n // Create container\r\n const container = document.createElement('div');\r\n container.style.width = '100%';\r\n container.style.height = '600px';\r\n container.style.position = 'relative';\r\n container.style.overflow = 'hidden';\r\n this.yasr.resultsEl.appendChild(container);\r\n \r\n // Get vis-network classes\r\n const { Network, DataSet } = getVisNetwork();\r\n \r\n // Create vis-network DataSets\r\n const nodesDataSet = new DataSet(nodes);\r\n const edgesDataSet = new DataSet(edges);\r\n \r\n // Initialize network\r\n const options = getDefaultNetworkOptions();\r\n this.network = new Network(\r\n container,\r\n { nodes: nodesDataSet, edges: edgesDataSet },\r\n options\r\n );\r\n \r\n // Track network readiness\r\n this.networkReady = false;\r\n \r\n // Disable physics after stabilization (performance optimization)\r\n this.network.on('stabilizationIterationsDone', () => {\r\n this.network.setOptions({ physics: { enabled: true } });\r\n this.networkReady = true;\r\n });\r\n \r\n // Add controls container AFTER network is created\r\n const controls = document.createElement('div');\r\n controls.style.position = 'absolute';\r\n controls.style.top = '10px';\r\n controls.style.right = '10px';\r\n controls.style.zIndex = '10000';\r\n controls.style.display = 'flex';\r\n controls.style.gap = '10px';\r\n controls.style.pointerEvents = 'auto';\r\n container.appendChild(controls);\r\n \r\n // Add \"Zoom to Fit\" button\r\n const fitButton = document.createElement('button');\r\n fitButton.textContent = 'Zoom to Fit';\r\n fitButton.style.padding = '8px 12px';\r\n fitButton.style.background = '#4CAF50';\r\n fitButton.style.color = 'white';\r\n fitButton.style.border = 'none';\r\n fitButton.style.borderRadius = '4px';\r\n fitButton.style.cursor = 'pointer';\r\n fitButton.style.fontSize = '14px';\r\n fitButton.style.boxShadow = '0 2px 4px rgba(0,0,0,0.2)';\r\n fitButton.onmouseover = () => fitButton.style.background = '#45a049';\r\n fitButton.onmouseout = () => fitButton.style.background = '#4CAF50';\r\n fitButton.onclick = () => {\r\n if (this.network) {\r\n this.network.fit({ animation: { duration: 300, easingFunction: 'easeInOutQuad' } });\r\n }\r\n };\r\n controls.appendChild(fitButton);\r\n \r\n // Add performance warning for large graphs\r\n if (triples.length > 1000) {\r\n console.warn('Large graph detected (>1000 triples). Rendering may be slow.');\r\n }\r\n \r\n } catch (error) {\r\n console.error('Error rendering graph:', error);\r\n this.yasr.resultsEl.innerHTML = '<div style=\"padding: 20px; color: red;\">Error rendering graph. See console for details.</div>';\r\n }\r\n }\r\n\r\n /**\r\n * Get icon for plugin tab\r\n * @returns {Element} Icon element\r\n */\r\n getIcon() {\r\n const icon = document.createElement('span');\r\n icon.className = 'fas fa-project-diagram';\r\n icon.setAttribute('aria-label', 'Graph visualization');\r\n return icon;\r\n }\r\n}\r\n\r\nexport default GraphPlugin;\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["src_exports", "__export", "src_default", "extractPrefixes", "yasrResults", "prefixMap", "vars", "prefix", "uri", "applyPrefix", "namespace", "localName", "truncateLabel", "text", "maxLength", "getDefaultNetworkOptions", "parseConstructResults", "yasrResults", "triples", "binding", "triple", "getNodeColor", "node", "triples", "triple", "createNodeMap", "triples", "prefixMap", "nodeMap", "nodeId", "triple", "isBlankNode", "label", "truncateLabel", "applyPrefix", "getNodeColor", "objValue", "isLiteral", "fullValue", "title", "createEdgesArray", "edges", "edgeSet", "fromNode", "toNode", "edgeKey", "triplesToGraph", "getVisNetwork", "GraphPlugin", "yasr", "results", "bindings", "firstBinding", "triples", "parseConstructResults", "prefixMap", "extractPrefixes", "nodes", "edges", "triplesToGraph", "container", "Network", "DataSet", "nodesDataSet", "edgesDataSet", "options", "getDefaultNetworkOptions", "controls", "fitButton", "error", "icon", "GraphPlugin_default", "GraphPlugin_default", "src_default"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,52 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@matdata/yasgui-graph-plugin",
|
|
3
|
-
"private": false,
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "YASGUI plugin for visualizing SPARQL CONSTRUCT and DESCRIBE query results as interactive graphs",
|
|
6
|
-
"main": "dist/yasgui-graph-plugin.
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"build": "
|
|
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
|
-
"eslint": "^8.0.0",
|
|
50
|
-
"prettier": "^3.0.0"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@matdata/yasgui-graph-plugin",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.3",
|
|
5
|
+
"description": "YASGUI plugin for visualizing SPARQL CONSTRUCT and DESCRIBE query results as interactive graphs",
|
|
6
|
+
"main": "dist/yasgui-graph-plugin.cjs.js",
|
|
7
|
+
"module": "dist/yasgui-graph-plugin.esm.js",
|
|
8
|
+
"unpkg": "dist/yasgui-graph-plugin.min.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "vite",
|
|
16
|
+
"build:demo": "vite build demo",
|
|
17
|
+
"preview:demo": "vite preview --port 5174",
|
|
18
|
+
"build": "node esbuild.config.js",
|
|
19
|
+
"test": "echo \"Manual browser testing per constitution\" && exit 0"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/Matdata-eu/yasgui-graph-plugin.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": ["yasgui", "sparql", "rdf", "graph", "visualization"],
|
|
26
|
+
"author": "Matdata",
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"type": "commonjs",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/Matdata-eu/yasgui-graph-plugin/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/Matdata-eu/yasgui-graph-plugin#readme",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"vis-network": "^9.1.9"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@zazuko/yasgui": "^4.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"vite": "^5.0.0",
|
|
44
|
+
"esbuild": "^0.19.0",
|
|
45
|
+
"eslint": "^8.0.0",
|
|
46
|
+
"prettier": "^3.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|