@loaders.gl/graphs 5.0.0-alpha.9 → 5.0.0-beta.10
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 +24 -0
- package/README.md +123 -4
- package/THIRD-PARTY-NOTICES.md +17 -0
- package/dist/dot-loader-types.cjs +60 -0
- package/dist/dot-loader-types.cjs.map +7 -0
- package/dist/dot-loader-types.d.ts +27 -8
- package/dist/dot-loader-types.d.ts.map +1 -1
- package/dist/dot-loader-types.js +3 -2
- package/dist/dot-loader-types.js.map +1 -1
- package/dist/dot-loader.cjs +358 -47
- package/dist/dot-loader.cjs.map +3 -3
- package/dist/dot-loader.d.ts +11 -6
- package/dist/dot-loader.d.ts.map +1 -1
- package/dist/dot-loader.js +3 -3
- package/dist/dot-loader.js.map +1 -1
- package/dist/dot-types.d.ts +6 -1
- package/dist/dot-types.d.ts.map +1 -1
- package/dist/gexf-loader-types.cjs +60 -0
- package/dist/gexf-loader-types.cjs.map +7 -0
- package/dist/gexf-loader-types.d.ts +55 -0
- package/dist/gexf-loader-types.d.ts.map +1 -0
- package/dist/gexf-loader-types.js +27 -0
- package/dist/gexf-loader-types.js.map +1 -0
- package/dist/gexf-loader.cjs +2669 -0
- package/dist/gexf-loader.cjs.map +6 -0
- package/dist/gexf-loader.d.ts +25 -0
- package/dist/gexf-loader.d.ts.map +1 -0
- package/dist/gexf-loader.js +13 -0
- package/dist/gexf-loader.js.map +1 -0
- package/dist/gexf-types.d.ts +16 -0
- package/dist/gexf-types.d.ts.map +1 -0
- package/dist/gexf-types.js +5 -0
- package/dist/gexf-types.js.map +1 -0
- package/dist/graph-types.d.ts +29 -0
- package/dist/graph-types.d.ts.map +1 -1
- package/dist/graphml-loader-types.cjs +60 -0
- package/dist/graphml-loader-types.cjs.map +7 -0
- package/dist/graphml-loader-types.d.ts +26 -8
- package/dist/graphml-loader-types.d.ts.map +1 -1
- package/dist/graphml-loader-types.js +3 -2
- package/dist/graphml-loader-types.js.map +1 -1
- package/dist/graphml-loader.cjs +2032 -69
- package/dist/graphml-loader.cjs.map +3 -3
- package/dist/graphml-loader.d.ts +11 -6
- package/dist/graphml-loader.d.ts.map +1 -1
- package/dist/graphml-loader.js +3 -3
- package/dist/graphml-loader.js.map +1 -1
- package/dist/index.cjs +59 -1085
- package/dist/index.cjs.map +4 -3
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/build-graph-tables.d.ts +4 -0
- package/dist/lib/build-graph-tables.d.ts.map +1 -0
- package/dist/lib/build-graph-tables.js +141 -0
- package/dist/lib/build-graph-tables.js.map +1 -0
- package/dist/lib/parse-dot.d.ts +3 -1
- package/dist/lib/parse-dot.d.ts.map +1 -1
- package/dist/lib/parse-dot.js +38 -21
- package/dist/lib/parse-dot.js.map +1 -1
- package/dist/lib/parse-gexf.d.ts +5 -0
- package/dist/lib/parse-gexf.d.ts.map +1 -0
- package/dist/lib/parse-gexf.js +382 -0
- package/dist/lib/parse-gexf.js.map +1 -0
- package/dist/lib/parse-graphml.d.ts +2 -1
- package/dist/lib/parse-graphml.d.ts.map +1 -1
- package/dist/lib/parse-graphml.js +54 -31
- package/dist/lib/parse-graphml.js.map +1 -1
- package/package.json +18 -8
- package/src/dot-loader-types.ts +16 -5
- package/src/dot-loader.ts +7 -4
- package/src/dot-types.ts +7 -1
- package/src/gexf-loader-types.ts +42 -0
- package/src/gexf-loader.ts +17 -0
- package/src/gexf-types.ts +21 -0
- package/src/graph-types.ts +36 -0
- package/src/graphml-loader-types.ts +15 -5
- package/src/graphml-loader.ts +7 -4
- package/src/index.ts +9 -0
- package/src/lib/build-graph-tables.ts +206 -0
- package/src/lib/parse-dot.ts +44 -21
- package/src/lib/parse-gexf.ts +390 -0
- package/src/lib/parse-graphml.ts +92 -40
package/dist/index.cjs
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __esm = (fn, res, err) => function __init() {
|
|
7
|
-
if (err) throw err[0];
|
|
8
|
-
try {
|
|
9
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
-
} catch (e) {
|
|
11
|
-
throw err = [e], e;
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
8
|
var __export = (target, all) => {
|
|
15
9
|
for (var name in all)
|
|
16
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -23,1114 +17,94 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
23
17
|
}
|
|
24
18
|
return to;
|
|
25
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
26
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
29
|
|
|
28
|
-
// src/graphml-loader-types.ts
|
|
29
|
-
async function preload() {
|
|
30
|
-
const { GraphMLLoaderWithParser: GraphMLLoaderWithParser2 } = await Promise.resolve().then(() => (init_graphml_loader(), graphml_loader_exports));
|
|
31
|
-
return GraphMLLoaderWithParser2;
|
|
32
|
-
}
|
|
33
|
-
var VERSION, GraphMLLoader;
|
|
34
|
-
var init_graphml_loader_types = __esm({
|
|
35
|
-
"src/graphml-loader-types.ts"() {
|
|
36
|
-
"use strict";
|
|
37
|
-
VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
38
|
-
GraphMLLoader = {
|
|
39
|
-
name: "GraphML",
|
|
40
|
-
id: "graphml",
|
|
41
|
-
module: "graphs",
|
|
42
|
-
version: VERSION,
|
|
43
|
-
extensions: ["graphml"],
|
|
44
|
-
mimeTypes: ["application/graphml+xml"],
|
|
45
|
-
text: true,
|
|
46
|
-
worker: false,
|
|
47
|
-
dataType: null,
|
|
48
|
-
batchType: null,
|
|
49
|
-
options: {},
|
|
50
|
-
preload
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// src/lib/parse-graphml.ts
|
|
56
|
-
function parseGraphML(graphml) {
|
|
57
|
-
const xmlText = decodeGraphML(graphml);
|
|
58
|
-
const document = graphmlParser.parse(xmlText);
|
|
59
|
-
const graphmlRoot = getGraphMLRoot(document);
|
|
60
|
-
if (!graphmlRoot) {
|
|
61
|
-
throw new Error("GraphML document does not contain a <graphml> element.");
|
|
62
|
-
}
|
|
63
|
-
const graphElement = getGraphElement(graphmlRoot);
|
|
64
|
-
if (!graphElement) {
|
|
65
|
-
throw new Error("GraphML document does not contain a <graph> element.");
|
|
66
|
-
}
|
|
67
|
-
const keyDefinitions = collectKeyDefinitions(graphmlRoot, graphElement);
|
|
68
|
-
const defaultDirected = parseEdgeDefault(graphElement[`${XML_ATTRIBUTE_PREFIX}edgedefault`]);
|
|
69
|
-
const nodes = normalizeArray(graphElement.node).map((node) => parseNode(node, keyDefinitions));
|
|
70
|
-
const edges = normalizeArray(graphElement.edge).map(
|
|
71
|
-
(edge, index) => parseEdge(edge, index, keyDefinitions, defaultDirected)
|
|
72
|
-
);
|
|
73
|
-
const filteredNodes = nodes.filter((node) => Boolean(node));
|
|
74
|
-
const filteredEdges = edges.filter((edge) => Boolean(edge));
|
|
75
|
-
return {
|
|
76
|
-
shape: "plain-graph-data",
|
|
77
|
-
nodes: filteredNodes,
|
|
78
|
-
edges: filteredEdges
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function decodeGraphML(graphml) {
|
|
82
|
-
if (typeof graphml === "string") {
|
|
83
|
-
return graphml;
|
|
84
|
-
}
|
|
85
|
-
if (graphml instanceof Uint8Array) {
|
|
86
|
-
return new TextDecoder().decode(graphml);
|
|
87
|
-
}
|
|
88
|
-
if (graphml instanceof ArrayBuffer) {
|
|
89
|
-
return new TextDecoder().decode(new Uint8Array(graphml));
|
|
90
|
-
}
|
|
91
|
-
throw new Error("Unsupported GraphML input. Expected a string, ArrayBuffer, or Uint8Array.");
|
|
92
|
-
}
|
|
93
|
-
function getGraphMLRoot(document) {
|
|
94
|
-
const root = document.graphml;
|
|
95
|
-
if (isObject(root)) {
|
|
96
|
-
return root;
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
function getGraphElement(graphmlRoot) {
|
|
101
|
-
const graph = graphmlRoot.graph;
|
|
102
|
-
if (!graph) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
if (Array.isArray(graph)) {
|
|
106
|
-
const firstGraph = graph.find((entry) => isObject(entry));
|
|
107
|
-
return isObject(firstGraph) ? firstGraph : null;
|
|
108
|
-
}
|
|
109
|
-
return isObject(graph) ? graph : null;
|
|
110
|
-
}
|
|
111
|
-
function collectKeyDefinitions(graphmlRoot, graphElement) {
|
|
112
|
-
const keys = /* @__PURE__ */ new Map();
|
|
113
|
-
for (const candidate of [
|
|
114
|
-
...normalizeArray(graphmlRoot.key),
|
|
115
|
-
...normalizeArray(graphElement.key)
|
|
116
|
-
]) {
|
|
117
|
-
if (isObject(candidate)) {
|
|
118
|
-
const id = String(candidate[`${XML_ATTRIBUTE_PREFIX}id`] ?? "").trim();
|
|
119
|
-
if (id) {
|
|
120
|
-
const domain = normalizeDomain(candidate[`${XML_ATTRIBUTE_PREFIX}for`]);
|
|
121
|
-
const name = String(candidate[`${XML_ATTRIBUTE_PREFIX}attr.name`] ?? id).trim();
|
|
122
|
-
const type = normalizeType(candidate[`${XML_ATTRIBUTE_PREFIX}attr.type`]);
|
|
123
|
-
const defaultNode = candidate.default ?? null;
|
|
124
|
-
const defaultValue = defaultNode !== null ? castDataValue(defaultNode, type) : void 0;
|
|
125
|
-
keys.set(id, { id, domain, name, type, defaultValue });
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return keys;
|
|
130
|
-
}
|
|
131
|
-
function parseNode(node, keyDefinitions) {
|
|
132
|
-
if (!isObject(node)) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
const id = node[`${XML_ATTRIBUTE_PREFIX}id`];
|
|
136
|
-
if (typeof id !== "string") {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
const attributes = buildAttributeBag("node", node.data, keyDefinitions);
|
|
140
|
-
const graphNode = {
|
|
141
|
-
id,
|
|
142
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
143
|
-
};
|
|
144
|
-
const label = attributes.label;
|
|
145
|
-
if (typeof label === "string") {
|
|
146
|
-
graphNode.label = label;
|
|
147
|
-
}
|
|
148
|
-
return graphNode;
|
|
149
|
-
}
|
|
150
|
-
function parseEdge(edge, index, keyDefinitions, defaultDirected) {
|
|
151
|
-
if (!isObject(edge)) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
const sourceId = edge[`${XML_ATTRIBUTE_PREFIX}source`];
|
|
155
|
-
const targetId = edge[`${XML_ATTRIBUTE_PREFIX}target`];
|
|
156
|
-
if (typeof sourceId !== "string") {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
if (typeof targetId !== "string") {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
const rawId = edge[`${XML_ATTRIBUTE_PREFIX}id`];
|
|
163
|
-
const id = typeof rawId === "string" ? rawId : `edge-${index}`;
|
|
164
|
-
const directed = parseDirected(edge[`${XML_ATTRIBUTE_PREFIX}directed`], defaultDirected);
|
|
165
|
-
const attributes = buildAttributeBag("edge", edge.data, keyDefinitions);
|
|
166
|
-
const graphEdge = {
|
|
167
|
-
id,
|
|
168
|
-
sourceId,
|
|
169
|
-
targetId,
|
|
170
|
-
directed,
|
|
171
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
172
|
-
};
|
|
173
|
-
const label = attributes.label;
|
|
174
|
-
if (typeof label === "string") {
|
|
175
|
-
graphEdge.label = label;
|
|
176
|
-
}
|
|
177
|
-
return graphEdge;
|
|
178
|
-
}
|
|
179
|
-
function buildAttributeBag(domain, data, keyDefinitions) {
|
|
180
|
-
const attributes = /* @__PURE__ */ Object.create(null);
|
|
181
|
-
for (const key of keyDefinitions.values()) {
|
|
182
|
-
if (key.domain === "all" || key.domain === domain) {
|
|
183
|
-
if (key.defaultValue !== void 0) {
|
|
184
|
-
attributes[key.name] = key.defaultValue;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
for (const entry of normalizeArray(data)) {
|
|
189
|
-
assignAttributeFromDataEntry(entry, keyDefinitions, attributes);
|
|
190
|
-
}
|
|
191
|
-
return attributes;
|
|
192
|
-
}
|
|
193
|
-
function assignAttributeFromDataEntry(entry, keyDefinitions, attributes) {
|
|
194
|
-
if (!isObject(entry)) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const keyId = entry[`${XML_ATTRIBUTE_PREFIX}key`];
|
|
198
|
-
if (typeof keyId !== "string") {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
const definition = keyDefinitions.get(keyId);
|
|
202
|
-
const attributeName = (definition == null ? void 0 : definition.name) ?? keyId;
|
|
203
|
-
const value = castDataValue(entry, (definition == null ? void 0 : definition.type) ?? "string");
|
|
204
|
-
if (value !== void 0) {
|
|
205
|
-
attributes[attributeName] = value;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
function castDataValue(value, type) {
|
|
209
|
-
if (value === null || typeof value === "undefined") {
|
|
210
|
-
return void 0;
|
|
211
|
-
}
|
|
212
|
-
const text = extractTextContent(value);
|
|
213
|
-
if (text === void 0) {
|
|
214
|
-
return void 0;
|
|
215
|
-
}
|
|
216
|
-
if (type === "boolean") {
|
|
217
|
-
return parseBoolean(text);
|
|
218
|
-
}
|
|
219
|
-
if (type === "int" || type === "long") {
|
|
220
|
-
const parsed = Number.parseInt(text, 10);
|
|
221
|
-
return Number.isNaN(parsed) ? text : parsed;
|
|
222
|
-
}
|
|
223
|
-
if (type === "float" || type === "double") {
|
|
224
|
-
const parsed = Number.parseFloat(text);
|
|
225
|
-
return Number.isNaN(parsed) ? text : parsed;
|
|
226
|
-
}
|
|
227
|
-
return text;
|
|
228
|
-
}
|
|
229
|
-
function extractTextContent(value) {
|
|
230
|
-
if (typeof value === "string") {
|
|
231
|
-
return value;
|
|
232
|
-
}
|
|
233
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
234
|
-
return String(value);
|
|
235
|
-
}
|
|
236
|
-
if (Array.isArray(value)) {
|
|
237
|
-
return extractTextContent(value[0]);
|
|
238
|
-
}
|
|
239
|
-
if (isObject(value)) {
|
|
240
|
-
const text = value[XML_TEXT_KEY];
|
|
241
|
-
if (typeof text === "string") {
|
|
242
|
-
return text;
|
|
243
|
-
}
|
|
244
|
-
const nonAttributeEntries = Object.entries(value).filter(
|
|
245
|
-
([key]) => !key.startsWith(XML_ATTRIBUTE_PREFIX)
|
|
246
|
-
);
|
|
247
|
-
if (nonAttributeEntries.length === 0) {
|
|
248
|
-
return void 0;
|
|
249
|
-
}
|
|
250
|
-
return JSON.stringify(Object.fromEntries(nonAttributeEntries));
|
|
251
|
-
}
|
|
252
|
-
return void 0;
|
|
253
|
-
}
|
|
254
|
-
function normalizeArray(value) {
|
|
255
|
-
if (!value) {
|
|
256
|
-
return [];
|
|
257
|
-
}
|
|
258
|
-
return Array.isArray(value) ? value : [value];
|
|
259
|
-
}
|
|
260
|
-
function isObject(value) {
|
|
261
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
262
|
-
}
|
|
263
|
-
function normalizeDomain(value) {
|
|
264
|
-
if (typeof value !== "string") {
|
|
265
|
-
return "all";
|
|
266
|
-
}
|
|
267
|
-
const lower = value.toLowerCase();
|
|
268
|
-
if (lower === "node" || lower === "edge" || lower === "graph" || lower === "all") {
|
|
269
|
-
return lower;
|
|
270
|
-
}
|
|
271
|
-
return "all";
|
|
272
|
-
}
|
|
273
|
-
function normalizeType(value) {
|
|
274
|
-
if (typeof value !== "string") {
|
|
275
|
-
return "string";
|
|
276
|
-
}
|
|
277
|
-
const lower = value.toLowerCase();
|
|
278
|
-
if (lower === "boolean" || lower === "int" || lower === "long" || lower === "float" || lower === "double") {
|
|
279
|
-
return lower;
|
|
280
|
-
}
|
|
281
|
-
return "string";
|
|
282
|
-
}
|
|
283
|
-
function parseEdgeDefault(value) {
|
|
284
|
-
if (typeof value !== "string") {
|
|
285
|
-
return false;
|
|
286
|
-
}
|
|
287
|
-
return value.toLowerCase() !== "undirected";
|
|
288
|
-
}
|
|
289
|
-
function parseDirected(value, defaultDirected) {
|
|
290
|
-
if (typeof value === "string") {
|
|
291
|
-
const normalized = value.trim().toLowerCase();
|
|
292
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "directed") {
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "undirected") {
|
|
296
|
-
return false;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return defaultDirected;
|
|
300
|
-
}
|
|
301
|
-
function parseBoolean(value) {
|
|
302
|
-
const normalized = value.trim().toLowerCase();
|
|
303
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y") {
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "n") {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
return Boolean(value);
|
|
310
|
-
}
|
|
311
|
-
var import_fast_xml_parser, XML_ATTRIBUTE_PREFIX, XML_TEXT_KEY, graphmlParser;
|
|
312
|
-
var init_parse_graphml = __esm({
|
|
313
|
-
"src/lib/parse-graphml.ts"() {
|
|
314
|
-
"use strict";
|
|
315
|
-
import_fast_xml_parser = require("fast-xml-parser");
|
|
316
|
-
XML_ATTRIBUTE_PREFIX = "@_";
|
|
317
|
-
XML_TEXT_KEY = "#text";
|
|
318
|
-
graphmlParser = new import_fast_xml_parser.XMLParser({
|
|
319
|
-
ignoreAttributes: false,
|
|
320
|
-
attributeNamePrefix: XML_ATTRIBUTE_PREFIX,
|
|
321
|
-
textNodeName: XML_TEXT_KEY,
|
|
322
|
-
trimValues: true,
|
|
323
|
-
parseAttributeValue: false,
|
|
324
|
-
parseTagValue: false,
|
|
325
|
-
removeNSPrefix: true
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
// src/graphml-loader.ts
|
|
331
|
-
var graphml_loader_exports = {};
|
|
332
|
-
__export(graphml_loader_exports, {
|
|
333
|
-
GraphMLLoaderWithParser: () => GraphMLLoaderWithParser
|
|
334
|
-
});
|
|
335
|
-
var GraphMLLoaderWithParser;
|
|
336
|
-
var init_graphml_loader = __esm({
|
|
337
|
-
"src/graphml-loader.ts"() {
|
|
338
|
-
"use strict";
|
|
339
|
-
init_graphml_loader_types();
|
|
340
|
-
init_parse_graphml();
|
|
341
|
-
GraphMLLoaderWithParser = {
|
|
342
|
-
...GraphMLLoader,
|
|
343
|
-
parse: async (data) => parseGraphML(data),
|
|
344
|
-
parseSync: parseGraphML,
|
|
345
|
-
parseTextSync: parseGraphML
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
// src/dot-loader-types.ts
|
|
351
|
-
async function preload3() {
|
|
352
|
-
const { DOTLoaderWithParser: DOTLoaderWithParser2 } = await Promise.resolve().then(() => (init_dot_loader(), dot_loader_exports));
|
|
353
|
-
return DOTLoaderWithParser2;
|
|
354
|
-
}
|
|
355
|
-
var VERSION3, DOTLoader;
|
|
356
|
-
var init_dot_loader_types = __esm({
|
|
357
|
-
"src/dot-loader-types.ts"() {
|
|
358
|
-
"use strict";
|
|
359
|
-
VERSION3 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
360
|
-
DOTLoader = {
|
|
361
|
-
name: "DOT",
|
|
362
|
-
id: "dot",
|
|
363
|
-
module: "graphs",
|
|
364
|
-
version: VERSION3,
|
|
365
|
-
extensions: ["dot", "gv"],
|
|
366
|
-
mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
|
|
367
|
-
text: true,
|
|
368
|
-
worker: false,
|
|
369
|
-
dataType: null,
|
|
370
|
-
batchType: null,
|
|
371
|
-
options: {},
|
|
372
|
-
preload: preload3
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
// src/lib/parse-dot.ts
|
|
378
|
-
function parseDOT(input) {
|
|
379
|
-
const parsed = parseDOTDocument(input);
|
|
380
|
-
const subgraphs = Array.from(parsed.subgraphs.values(), (subgraph) => ({
|
|
381
|
-
...subgraph,
|
|
382
|
-
attributes: { ...subgraph.attributes }
|
|
383
|
-
}));
|
|
384
|
-
return {
|
|
385
|
-
shape: "plain-graph-data",
|
|
386
|
-
nodes: Array.from(parsed.nodes.values(), (node) => ({
|
|
387
|
-
id: node.id,
|
|
388
|
-
...typeof node.attributes.label === "string" ? { label: node.attributes.label } : {},
|
|
389
|
-
attributes: {
|
|
390
|
-
...node.attributes,
|
|
391
|
-
...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) => describeSubgraph(id, parsed.subgraphs)) } : {}
|
|
392
|
-
}
|
|
393
|
-
})),
|
|
394
|
-
edges: parsed.edges.map((edge) => ({
|
|
395
|
-
id: edge.id,
|
|
396
|
-
sourceId: edge.sourceId,
|
|
397
|
-
targetId: edge.targetId,
|
|
398
|
-
directed: edge.directed,
|
|
399
|
-
...typeof edge.attributes.label === "string" ? { label: edge.attributes.label } : {},
|
|
400
|
-
attributes: {
|
|
401
|
-
...edge.attributes,
|
|
402
|
-
...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) => describeSubgraph(id, parsed.subgraphs)) } : {}
|
|
403
|
-
}
|
|
404
|
-
})),
|
|
405
|
-
metadata: {
|
|
406
|
-
id: parsed.id,
|
|
407
|
-
directed: parsed.directed,
|
|
408
|
-
strict: parsed.strict,
|
|
409
|
-
attributes: { ...parsed.graphAttributes },
|
|
410
|
-
subgraphs
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
function describeSubgraph(id, descriptors) {
|
|
415
|
-
const subgraph = descriptors.get(id);
|
|
416
|
-
return {
|
|
417
|
-
id,
|
|
418
|
-
attributes: { ...subgraph.attributes },
|
|
419
|
-
parentId: subgraph.parentId
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
function parseDOTDocument(input) {
|
|
423
|
-
const parser = new DOTParser(tokenize(input));
|
|
424
|
-
return parser.parse();
|
|
425
|
-
}
|
|
426
|
-
function tokenize(input) {
|
|
427
|
-
const tokens = [];
|
|
428
|
-
let index = 0;
|
|
429
|
-
while (index < input.length) {
|
|
430
|
-
const { token, nextIndex } = readNextToken(input, index);
|
|
431
|
-
if (nextIndex <= index) {
|
|
432
|
-
throw new Error(`Tokenizer did not advance at position ${index}.`);
|
|
433
|
-
}
|
|
434
|
-
if (token) {
|
|
435
|
-
tokens.push(token);
|
|
436
|
-
}
|
|
437
|
-
index = nextIndex;
|
|
438
|
-
}
|
|
439
|
-
return tokens;
|
|
440
|
-
}
|
|
441
|
-
function readNextToken(input, index) {
|
|
442
|
-
if (index >= input.length) {
|
|
443
|
-
return { token: null, nextIndex: input.length };
|
|
444
|
-
}
|
|
445
|
-
const character = input[index];
|
|
446
|
-
if (isWhitespace(character)) {
|
|
447
|
-
return { token: null, nextIndex: index + 1 };
|
|
448
|
-
}
|
|
449
|
-
const commentEnd = skipComment(input, index);
|
|
450
|
-
if (commentEnd !== null) {
|
|
451
|
-
return { token: null, nextIndex: commentEnd };
|
|
452
|
-
}
|
|
453
|
-
const arrowToken = readArrowToken(input, index);
|
|
454
|
-
if (arrowToken) {
|
|
455
|
-
return arrowToken;
|
|
456
|
-
}
|
|
457
|
-
const punctuation = readPunctuationToken(character);
|
|
458
|
-
if (punctuation) {
|
|
459
|
-
return { token: punctuation, nextIndex: index + 1 };
|
|
460
|
-
}
|
|
461
|
-
if (character === '"') {
|
|
462
|
-
const { value, nextIndex } = readQuotedString(input, index + 1);
|
|
463
|
-
return { token: { type: "string", value }, nextIndex };
|
|
464
|
-
}
|
|
465
|
-
if (character === "<") {
|
|
466
|
-
const { value, nextIndex } = readHtmlString(input, index + 1);
|
|
467
|
-
return { token: { type: "html", value }, nextIndex };
|
|
468
|
-
}
|
|
469
|
-
const identifier = readIdentifier(input, index);
|
|
470
|
-
if (identifier.value) {
|
|
471
|
-
return {
|
|
472
|
-
token: { type: "identifier", value: identifier.value },
|
|
473
|
-
nextIndex: identifier.nextIndex
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
throw new Error(`Unexpected token at position ${index}.`);
|
|
477
|
-
}
|
|
478
|
-
function skipComment(input, index) {
|
|
479
|
-
const character = input[index];
|
|
480
|
-
if (character === "/") {
|
|
481
|
-
const next = input[index + 1];
|
|
482
|
-
if (next === "/") {
|
|
483
|
-
return skipLineComment(input, index + 2);
|
|
484
|
-
}
|
|
485
|
-
if (next === "*") {
|
|
486
|
-
return skipBlockComment(input, index + 2);
|
|
487
|
-
}
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
if (character === "#") {
|
|
491
|
-
return skipLineComment(input, index + 1);
|
|
492
|
-
}
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
function skipLineComment(input, startIndex) {
|
|
496
|
-
let cursor = startIndex;
|
|
497
|
-
while (cursor < input.length && !isLineBreak(input[cursor])) {
|
|
498
|
-
cursor++;
|
|
499
|
-
}
|
|
500
|
-
return cursor;
|
|
501
|
-
}
|
|
502
|
-
function skipBlockComment(input, startIndex) {
|
|
503
|
-
let cursor = startIndex;
|
|
504
|
-
while (cursor < input.length) {
|
|
505
|
-
if (input[cursor] === "*" && input[cursor + 1] === "/") {
|
|
506
|
-
return cursor + 2;
|
|
507
|
-
}
|
|
508
|
-
cursor++;
|
|
509
|
-
}
|
|
510
|
-
throw new Error("Unterminated block comment in DOT source.");
|
|
511
|
-
}
|
|
512
|
-
function readArrowToken(input, index) {
|
|
513
|
-
const next = input[index + 1];
|
|
514
|
-
if (input[index] === "-" && next === "-") {
|
|
515
|
-
return { token: { type: "arrow", value: "--" }, nextIndex: index + 2 };
|
|
516
|
-
}
|
|
517
|
-
if (input[index] === "-" && next === ">") {
|
|
518
|
-
return { token: { type: "arrow", value: "->" }, nextIndex: index + 2 };
|
|
519
|
-
}
|
|
520
|
-
return null;
|
|
521
|
-
}
|
|
522
|
-
function readPunctuationToken(character) {
|
|
523
|
-
switch (character) {
|
|
524
|
-
case "{":
|
|
525
|
-
return { type: "lbrace", value: character };
|
|
526
|
-
case "}":
|
|
527
|
-
return { type: "rbrace", value: character };
|
|
528
|
-
case "[":
|
|
529
|
-
return { type: "lbrack", value: character };
|
|
530
|
-
case "]":
|
|
531
|
-
return { type: "rbrack", value: character };
|
|
532
|
-
case "=":
|
|
533
|
-
return { type: "equals", value: character };
|
|
534
|
-
case ",":
|
|
535
|
-
return { type: "comma", value: character };
|
|
536
|
-
case ";":
|
|
537
|
-
return { type: "semicolon", value: character };
|
|
538
|
-
default:
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
function readQuotedString(input, startIndex) {
|
|
543
|
-
let value = "";
|
|
544
|
-
let index = startIndex;
|
|
545
|
-
while (index < input.length) {
|
|
546
|
-
const character = input[index];
|
|
547
|
-
if (character === '"') {
|
|
548
|
-
return { value, nextIndex: index + 1 };
|
|
549
|
-
}
|
|
550
|
-
if (character === "\\") {
|
|
551
|
-
const escape = readEscapedCharacter(input, index + 1);
|
|
552
|
-
value += escape.value;
|
|
553
|
-
index = escape.nextIndex;
|
|
554
|
-
} else {
|
|
555
|
-
value += character;
|
|
556
|
-
index++;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
throw new Error("Unterminated string literal in DOT source.");
|
|
560
|
-
}
|
|
561
|
-
function readEscapedCharacter(input, startIndex) {
|
|
562
|
-
const next = input[startIndex];
|
|
563
|
-
switch (next) {
|
|
564
|
-
case "n":
|
|
565
|
-
case "l":
|
|
566
|
-
case "L":
|
|
567
|
-
return { value: "\n", nextIndex: startIndex + 1 };
|
|
568
|
-
case "t":
|
|
569
|
-
return { value: " ", nextIndex: startIndex + 1 };
|
|
570
|
-
case "r":
|
|
571
|
-
return { value: "\r", nextIndex: startIndex + 1 };
|
|
572
|
-
case '"':
|
|
573
|
-
return { value: '"', nextIndex: startIndex + 1 };
|
|
574
|
-
case "\\":
|
|
575
|
-
return { value: "\\", nextIndex: startIndex + 1 };
|
|
576
|
-
default: {
|
|
577
|
-
if (typeof next === "undefined") {
|
|
578
|
-
throw new Error("Unterminated escape sequence in DOT source.");
|
|
579
|
-
}
|
|
580
|
-
return { value: next, nextIndex: startIndex + 1 };
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
function readHtmlString(input, startIndex) {
|
|
585
|
-
let value = "<";
|
|
586
|
-
let depth = 1;
|
|
587
|
-
let index = startIndex;
|
|
588
|
-
while (index < input.length) {
|
|
589
|
-
const character = input[index];
|
|
590
|
-
value += character;
|
|
591
|
-
if (character === "<") {
|
|
592
|
-
depth++;
|
|
593
|
-
} else if (character === ">") {
|
|
594
|
-
depth--;
|
|
595
|
-
if (depth === 0) {
|
|
596
|
-
return { value, nextIndex: index + 1 };
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
index++;
|
|
600
|
-
}
|
|
601
|
-
throw new Error("Unterminated HTML-like string literal in DOT source.");
|
|
602
|
-
}
|
|
603
|
-
function readIdentifier(input, startIndex) {
|
|
604
|
-
let index = startIndex;
|
|
605
|
-
let value = "";
|
|
606
|
-
while (index < input.length && !isIdentifierTerminator(input, index)) {
|
|
607
|
-
value += input[index];
|
|
608
|
-
index++;
|
|
609
|
-
}
|
|
610
|
-
if (value.includes(":")) {
|
|
611
|
-
throw new Error("DOT node ports are not supported; quote identifiers containing colons.");
|
|
612
|
-
}
|
|
613
|
-
return { value, nextIndex: index };
|
|
614
|
-
}
|
|
615
|
-
function isIdentifierTerminator(input, index) {
|
|
616
|
-
const character = input[index];
|
|
617
|
-
if (isWhitespace(character) || IDENTIFIER_TERMINATORS.has(character)) {
|
|
618
|
-
return true;
|
|
619
|
-
}
|
|
620
|
-
if (isArrowOperatorStart(input, index)) {
|
|
621
|
-
return true;
|
|
622
|
-
}
|
|
623
|
-
if (isCommentStart(input, index)) {
|
|
624
|
-
return true;
|
|
625
|
-
}
|
|
626
|
-
return false;
|
|
627
|
-
}
|
|
628
|
-
function isArrowOperatorStart(input, index) {
|
|
629
|
-
if (input[index] !== "-") {
|
|
630
|
-
return false;
|
|
631
|
-
}
|
|
632
|
-
const next = input[index + 1];
|
|
633
|
-
return next === "-" || next === ">";
|
|
634
|
-
}
|
|
635
|
-
function isCommentStart(input, index) {
|
|
636
|
-
if (input[index] !== "/") {
|
|
637
|
-
return false;
|
|
638
|
-
}
|
|
639
|
-
const next = input[index + 1];
|
|
640
|
-
return next === "/" || next === "*";
|
|
641
|
-
}
|
|
642
|
-
function isWhitespace(character) {
|
|
643
|
-
return character === " " || character === "\n" || character === "\r" || character === " " || character === "\f";
|
|
644
|
-
}
|
|
645
|
-
function isLineBreak(character) {
|
|
646
|
-
return character === "\n" || character === "\r";
|
|
647
|
-
}
|
|
648
|
-
function isKeyword(token, keyword) {
|
|
649
|
-
return token.type === "identifier" && token.value.toLowerCase() === keyword.toLowerCase();
|
|
650
|
-
}
|
|
651
|
-
function isGraphType(token) {
|
|
652
|
-
return isKeyword(token, "graph") || isKeyword(token, "digraph");
|
|
653
|
-
}
|
|
654
|
-
function isIdentifierLike(token) {
|
|
655
|
-
return token.type === "identifier" || token.type === "string" || token.type === "html";
|
|
656
|
-
}
|
|
657
|
-
function parseIdentifierValue(token) {
|
|
658
|
-
return token.value;
|
|
659
|
-
}
|
|
660
|
-
function parseAttributeValue(token) {
|
|
661
|
-
if (token.type === "string" || token.type === "html") {
|
|
662
|
-
return token.value;
|
|
663
|
-
}
|
|
664
|
-
if (token.type === "identifier") {
|
|
665
|
-
const numeric = Number(token.value);
|
|
666
|
-
if (!Number.isNaN(numeric)) {
|
|
667
|
-
return numeric;
|
|
668
|
-
}
|
|
669
|
-
return token.value;
|
|
670
|
-
}
|
|
671
|
-
throw new Error("Invalid attribute value in DOT input.");
|
|
672
|
-
}
|
|
673
|
-
function deriveEdgeId(attributes, sourceId, targetId, counter) {
|
|
674
|
-
const candidate = attributes.id ?? attributes.Id ?? attributes.ID;
|
|
675
|
-
if (typeof candidate === "string" || typeof candidate === "number") {
|
|
676
|
-
return String(candidate);
|
|
677
|
-
}
|
|
678
|
-
return `${String(sourceId)}-${String(targetId)}-${counter}`;
|
|
679
|
-
}
|
|
680
|
-
function deriveDirectedFlag(attributes, defaultDirected) {
|
|
681
|
-
const candidate = attributes.directed;
|
|
682
|
-
if (typeof candidate === "boolean") {
|
|
683
|
-
return candidate;
|
|
684
|
-
}
|
|
685
|
-
const directionAttribute = attributes.dir;
|
|
686
|
-
if (typeof directionAttribute === "string") {
|
|
687
|
-
const normalized = directionAttribute.toLowerCase();
|
|
688
|
-
if (normalized === "none") {
|
|
689
|
-
return false;
|
|
690
|
-
}
|
|
691
|
-
return true;
|
|
692
|
-
}
|
|
693
|
-
return defaultDirected;
|
|
694
|
-
}
|
|
695
|
-
var DOTParser, IDENTIFIER_TERMINATORS;
|
|
696
|
-
var init_parse_dot = __esm({
|
|
697
|
-
"src/lib/parse-dot.ts"() {
|
|
698
|
-
"use strict";
|
|
699
|
-
DOTParser = class {
|
|
700
|
-
/** Tokens for DOT parsing. */
|
|
701
|
-
tokens;
|
|
702
|
-
/** Position for DOT parsing. */
|
|
703
|
-
position = 0;
|
|
704
|
-
/** Accumulated graph records and attributes. */
|
|
705
|
-
result = {
|
|
706
|
-
directed: false,
|
|
707
|
-
strict: false,
|
|
708
|
-
graphAttributes: /* @__PURE__ */ Object.create(null),
|
|
709
|
-
nodes: /* @__PURE__ */ new Map(),
|
|
710
|
-
edges: [],
|
|
711
|
-
subgraphs: /* @__PURE__ */ new Map()
|
|
712
|
-
};
|
|
713
|
-
/** Scopes for DOT parsing. */
|
|
714
|
-
scopes = [
|
|
715
|
-
{
|
|
716
|
-
nodeDefaults: /* @__PURE__ */ Object.create(null),
|
|
717
|
-
edgeDefaults: /* @__PURE__ */ Object.create(null),
|
|
718
|
-
graphAttributes: /* @__PURE__ */ Object.create(null)
|
|
719
|
-
}
|
|
720
|
-
];
|
|
721
|
-
/** Subgraph counter for DOT parsing. */
|
|
722
|
-
subgraphCounter = 0;
|
|
723
|
-
/** Edge counter for DOT parsing. */
|
|
724
|
-
edgeCounter = 0;
|
|
725
|
-
/** Edge lookup used to coalesce parallel edges in strict graphs. */
|
|
726
|
-
strictEdges = /* @__PURE__ */ new Map();
|
|
727
|
-
/** Persistent attributes and defaults for reopened named subgraphs. */
|
|
728
|
-
subgraphScopes = /* @__PURE__ */ new Map();
|
|
729
|
-
/** Explicit names reserved so anonymous subgraph IDs cannot collide with them. */
|
|
730
|
-
namedSubgraphIds = /* @__PURE__ */ new Set();
|
|
731
|
-
/** Initializes the token stream. */
|
|
732
|
-
constructor(tokens) {
|
|
733
|
-
this.tokens = tokens;
|
|
734
|
-
for (let index = 0; index < tokens.length - 1; index++) {
|
|
735
|
-
if (isKeyword(tokens[index], "subgraph") && isIdentifierLike(tokens[index + 1])) {
|
|
736
|
-
this.namedSubgraphIds.add(tokens[index + 1].value);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
/** Parses one complete DOT document. */
|
|
741
|
-
parse() {
|
|
742
|
-
this.parseGraph();
|
|
743
|
-
this.consumeOptionalSemicolon();
|
|
744
|
-
if (this.peek()) {
|
|
745
|
-
throw new Error("Unexpected content after DOT graph.");
|
|
746
|
-
}
|
|
747
|
-
return this.result;
|
|
748
|
-
}
|
|
749
|
-
/** Reads graph identity, declaration, and statements. */
|
|
750
|
-
parseGraph() {
|
|
751
|
-
const strictToken = this.peek();
|
|
752
|
-
if (strictToken && isKeyword(strictToken, "strict")) {
|
|
753
|
-
this.consume();
|
|
754
|
-
this.result.strict = true;
|
|
755
|
-
}
|
|
756
|
-
const typeToken = this.peek();
|
|
757
|
-
if (!typeToken || !isGraphType(typeToken)) {
|
|
758
|
-
throw new Error("DOT graph must start with graph or digraph keyword.");
|
|
759
|
-
}
|
|
760
|
-
this.consume();
|
|
761
|
-
this.result.directed = isKeyword(typeToken, "digraph");
|
|
762
|
-
const idToken = this.peek();
|
|
763
|
-
if (idToken && isIdentifierLike(idToken)) {
|
|
764
|
-
this.result.id = parseIdentifierValue(this.consume());
|
|
765
|
-
}
|
|
766
|
-
this.expect("lbrace");
|
|
767
|
-
while (!this.match("rbrace")) {
|
|
768
|
-
if (!this.parseStatement()) {
|
|
769
|
-
throw new Error("Expected closing brace in DOT graph.");
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
this.result.graphAttributes = { ...this.scopes[0].graphAttributes };
|
|
773
|
-
}
|
|
774
|
-
/** Dispatches a graph statement. */
|
|
775
|
-
parseStatement() {
|
|
776
|
-
if (this.consumeSemicolonIfPresent()) {
|
|
777
|
-
return true;
|
|
778
|
-
}
|
|
779
|
-
const token = this.peek();
|
|
780
|
-
if (!token) {
|
|
781
|
-
return false;
|
|
782
|
-
}
|
|
783
|
-
if (this.tryParseSubgraphStatement(token)) {
|
|
784
|
-
return true;
|
|
785
|
-
}
|
|
786
|
-
if (this.tryParseKeywordStatement(token)) {
|
|
787
|
-
return true;
|
|
788
|
-
}
|
|
789
|
-
if (this.tryParseAssignmentStatement(token)) {
|
|
790
|
-
return true;
|
|
791
|
-
}
|
|
792
|
-
if (isIdentifierLike(token)) {
|
|
793
|
-
this.parseNodeOrEdgeStatement();
|
|
794
|
-
this.consumeOptionalSemicolon();
|
|
795
|
-
return true;
|
|
796
|
-
}
|
|
797
|
-
throw new Error(`Unexpected token: ${token.value}`);
|
|
798
|
-
}
|
|
799
|
-
/** Consumes an empty statement. */
|
|
800
|
-
consumeSemicolonIfPresent() {
|
|
801
|
-
const next = this.peek();
|
|
802
|
-
if ((next == null ? void 0 : next.type) === "semicolon") {
|
|
803
|
-
this.consume();
|
|
804
|
-
return true;
|
|
805
|
-
}
|
|
806
|
-
return false;
|
|
807
|
-
}
|
|
808
|
-
/** Reads a standalone subgraph statement. */
|
|
809
|
-
tryParseSubgraphStatement(token) {
|
|
810
|
-
if (token.type !== "lbrace" && !isKeyword(token, "subgraph")) {
|
|
811
|
-
return false;
|
|
812
|
-
}
|
|
813
|
-
this.parseSubgraph();
|
|
814
|
-
return true;
|
|
815
|
-
}
|
|
816
|
-
/** Applies graph, node, or edge defaults. */
|
|
817
|
-
tryParseKeywordStatement(token) {
|
|
818
|
-
if (!(isKeyword(token, "graph") || isKeyword(token, "node") || isKeyword(token, "edge"))) {
|
|
819
|
-
return false;
|
|
820
|
-
}
|
|
821
|
-
this.consume();
|
|
822
|
-
const explicitAttributes = this.parseAttributeList();
|
|
823
|
-
if (isKeyword(token, "graph")) {
|
|
824
|
-
Object.assign(this.currentScope().graphAttributes, explicitAttributes);
|
|
825
|
-
} else if (isKeyword(token, "node")) {
|
|
826
|
-
Object.assign(this.currentScope().nodeDefaults, explicitAttributes);
|
|
827
|
-
} else {
|
|
828
|
-
Object.assign(this.currentScope().edgeDefaults, explicitAttributes);
|
|
829
|
-
}
|
|
830
|
-
this.consumeOptionalSemicolon();
|
|
831
|
-
return true;
|
|
832
|
-
}
|
|
833
|
-
/** Reads a graph attribute assignment. */
|
|
834
|
-
tryParseAssignmentStatement(token) {
|
|
835
|
-
if (!isIdentifierLike(token)) {
|
|
836
|
-
return false;
|
|
837
|
-
}
|
|
838
|
-
const next = this.peek(1);
|
|
839
|
-
if ((next == null ? void 0 : next.type) !== "equals") {
|
|
840
|
-
return false;
|
|
841
|
-
}
|
|
842
|
-
const key = parseIdentifierValue(this.consume());
|
|
843
|
-
this.consume();
|
|
844
|
-
const valueToken = this.consume();
|
|
845
|
-
const value = parseAttributeValue(valueToken);
|
|
846
|
-
this.currentScope().graphAttributes[key] = value;
|
|
847
|
-
this.consumeOptionalSemicolon();
|
|
848
|
-
return true;
|
|
849
|
-
}
|
|
850
|
-
/** Reads a node statement or chained edges. */
|
|
851
|
-
parseNodeOrEdgeStatement() {
|
|
852
|
-
const first = parseIdentifierValue(this.consume());
|
|
853
|
-
const references = [first];
|
|
854
|
-
const operators = [];
|
|
855
|
-
let operatorToken = this.match("arrow");
|
|
856
|
-
while (operatorToken) {
|
|
857
|
-
operators.push(operatorToken.value);
|
|
858
|
-
const referenceToken = this.consume();
|
|
859
|
-
if (!isIdentifierLike(referenceToken)) {
|
|
860
|
-
throw new Error("Expected node identifier in edge statement.");
|
|
861
|
-
}
|
|
862
|
-
references.push(parseIdentifierValue(referenceToken));
|
|
863
|
-
operatorToken = this.match("arrow");
|
|
864
|
-
}
|
|
865
|
-
if (operators.length === 0) {
|
|
866
|
-
const explicitAttributes2 = this.parseAttributeList();
|
|
867
|
-
this.addNode(first, explicitAttributes2);
|
|
868
|
-
return;
|
|
869
|
-
}
|
|
870
|
-
const explicitAttributes = this.parseAttributeList();
|
|
871
|
-
this.addEdgeChain(references, operators, explicitAttributes);
|
|
872
|
-
}
|
|
873
|
-
/** Merges explicit attributes into a node. */
|
|
874
|
-
addNode(id, explicitAttributes) {
|
|
875
|
-
const membership = this.getCurrentSubgraphChain();
|
|
876
|
-
const node = this.ensureNode(id, membership);
|
|
877
|
-
node.attributes = { ...node.attributes, ...explicitAttributes };
|
|
878
|
-
}
|
|
879
|
-
/** Expands an edge chain into node and edge records. */
|
|
880
|
-
addEdgeChain(nodes, operators, explicitAttributes) {
|
|
881
|
-
const membership = this.getCurrentSubgraphChain();
|
|
882
|
-
const defaults = this.currentScope().edgeDefaults;
|
|
883
|
-
const attributes = { ...defaults, ...explicitAttributes };
|
|
884
|
-
for (let index = 0; index < nodes.length - 1; index++) {
|
|
885
|
-
const sourceId = nodes[index];
|
|
886
|
-
const targetId = nodes[index + 1];
|
|
887
|
-
const operator = operators[index];
|
|
888
|
-
const directed = operator === "->";
|
|
889
|
-
if (directed !== this.result.directed) {
|
|
890
|
-
throw new Error("DOT edge operator must match graph or digraph declaration.");
|
|
891
|
-
}
|
|
892
|
-
const edgeId = deriveEdgeId(attributes, sourceId, targetId, ++this.edgeCounter);
|
|
893
|
-
const edgeAttributes = { ...attributes };
|
|
894
|
-
this.ensureNode(sourceId, membership);
|
|
895
|
-
this.ensureNode(targetId, membership);
|
|
896
|
-
const strictKey = JSON.stringify(
|
|
897
|
-
directed ? [sourceId, targetId] : [sourceId, targetId].sort()
|
|
898
|
-
);
|
|
899
|
-
const existingEdge = this.result.strict ? this.strictEdges.get(strictKey) : void 0;
|
|
900
|
-
if (existingEdge) {
|
|
901
|
-
existingEdge.attributes = { ...existingEdge.attributes, ...explicitAttributes };
|
|
902
|
-
existingEdge.directed = deriveDirectedFlag(existingEdge.attributes, directed);
|
|
903
|
-
existingEdge.subgraphs = Array.from(/* @__PURE__ */ new Set([...existingEdge.subgraphs, ...membership]));
|
|
904
|
-
continue;
|
|
905
|
-
}
|
|
906
|
-
const directedOverride = deriveDirectedFlag(edgeAttributes, directed);
|
|
907
|
-
const edge = {
|
|
908
|
-
id: edgeId,
|
|
909
|
-
sourceId,
|
|
910
|
-
targetId,
|
|
911
|
-
directed: directedOverride,
|
|
912
|
-
attributes: edgeAttributes,
|
|
913
|
-
subgraphs: membership
|
|
914
|
-
};
|
|
915
|
-
this.result.edges.push(edge);
|
|
916
|
-
if (this.result.strict) {
|
|
917
|
-
this.strictEdges.set(strictKey, edge);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
/** Reads a nested scope with inherited defaults. */
|
|
922
|
-
parseSubgraph() {
|
|
923
|
-
let idToken = this.peek();
|
|
924
|
-
let subgraphId;
|
|
925
|
-
if (idToken && isKeyword(idToken, "subgraph")) {
|
|
926
|
-
this.consume();
|
|
927
|
-
idToken = this.peek();
|
|
928
|
-
}
|
|
929
|
-
if (idToken && isIdentifierLike(idToken)) {
|
|
930
|
-
subgraphId = parseIdentifierValue(this.consume());
|
|
931
|
-
} else {
|
|
932
|
-
do {
|
|
933
|
-
subgraphId = `subgraph_${++this.subgraphCounter}`;
|
|
934
|
-
} while (this.namedSubgraphIds.has(subgraphId));
|
|
935
|
-
}
|
|
936
|
-
this.expect("lbrace");
|
|
937
|
-
const parentId = this.findCurrentSubgraphId();
|
|
938
|
-
let context = this.subgraphScopes.get(subgraphId);
|
|
939
|
-
if (!context) {
|
|
940
|
-
context = {
|
|
941
|
-
id: subgraphId,
|
|
942
|
-
nodeDefaults: Object.assign(/* @__PURE__ */ Object.create(null), this.currentScope().nodeDefaults),
|
|
943
|
-
edgeDefaults: Object.assign(/* @__PURE__ */ Object.create(null), this.currentScope().edgeDefaults),
|
|
944
|
-
graphAttributes: /* @__PURE__ */ Object.create(null)
|
|
945
|
-
};
|
|
946
|
-
this.subgraphScopes.set(subgraphId, context);
|
|
947
|
-
this.result.subgraphs.set(subgraphId, {
|
|
948
|
-
id: subgraphId,
|
|
949
|
-
attributes: context.graphAttributes,
|
|
950
|
-
parentId
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
this.scopes.push(context);
|
|
954
|
-
let shouldContinue = true;
|
|
955
|
-
while (shouldContinue) {
|
|
956
|
-
if (this.match("rbrace")) {
|
|
957
|
-
break;
|
|
958
|
-
}
|
|
959
|
-
shouldContinue = this.parseStatement();
|
|
960
|
-
if (!shouldContinue) {
|
|
961
|
-
throw new Error("Expected closing brace in DOT subgraph.");
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
this.scopes.pop();
|
|
965
|
-
}
|
|
966
|
-
/** Reads repeated attribute lists. */
|
|
967
|
-
parseAttributeList() {
|
|
968
|
-
var _a, _b;
|
|
969
|
-
const attributes = /* @__PURE__ */ Object.create(null);
|
|
970
|
-
while (this.match("lbrack")) {
|
|
971
|
-
while (!this.match("rbrack")) {
|
|
972
|
-
const keyToken = this.consume();
|
|
973
|
-
if (!isIdentifierLike(keyToken)) {
|
|
974
|
-
throw new Error("Expected attribute name.");
|
|
975
|
-
}
|
|
976
|
-
const key = parseIdentifierValue(keyToken);
|
|
977
|
-
let value = true;
|
|
978
|
-
if (this.match("equals")) {
|
|
979
|
-
const valueToken = this.consume();
|
|
980
|
-
value = parseAttributeValue(valueToken);
|
|
981
|
-
}
|
|
982
|
-
attributes[key] = value;
|
|
983
|
-
if (((_a = this.peek()) == null ? void 0 : _a.type) === "comma" || ((_b = this.peek()) == null ? void 0 : _b.type) === "semicolon") {
|
|
984
|
-
this.consume();
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
return attributes;
|
|
989
|
-
}
|
|
990
|
-
/** Creates an implicit node and records its subgraph memberships. */
|
|
991
|
-
ensureNode(id, membership) {
|
|
992
|
-
let node = this.result.nodes.get(id);
|
|
993
|
-
if (!node) {
|
|
994
|
-
const defaults = this.currentScope().nodeDefaults;
|
|
995
|
-
node = { id, attributes: { ...defaults }, subgraphs: /* @__PURE__ */ new Set() };
|
|
996
|
-
this.result.nodes.set(id, node);
|
|
997
|
-
}
|
|
998
|
-
membership.forEach((subgraphId) => node.subgraphs.add(subgraphId));
|
|
999
|
-
return node;
|
|
1000
|
-
}
|
|
1001
|
-
/** Lists enclosing subgraphs. */
|
|
1002
|
-
getCurrentSubgraphChain() {
|
|
1003
|
-
const chain = [];
|
|
1004
|
-
for (const scope of this.scopes) {
|
|
1005
|
-
if (scope.id) {
|
|
1006
|
-
chain.push(scope.id);
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
return chain;
|
|
1010
|
-
}
|
|
1011
|
-
/** Finds the nearest enclosing named or generated subgraph. */
|
|
1012
|
-
findCurrentSubgraphId() {
|
|
1013
|
-
for (let index = this.scopes.length - 1; index >= 0; index--) {
|
|
1014
|
-
const scope = this.scopes[index];
|
|
1015
|
-
if (scope.id) {
|
|
1016
|
-
return scope.id;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
return void 0;
|
|
1020
|
-
}
|
|
1021
|
-
/** Returns the active attribute scope. */
|
|
1022
|
-
currentScope() {
|
|
1023
|
-
return this.scopes[this.scopes.length - 1];
|
|
1024
|
-
}
|
|
1025
|
-
/** Consumes an optional statement terminator. */
|
|
1026
|
-
consumeOptionalSemicolon() {
|
|
1027
|
-
const next = this.peek();
|
|
1028
|
-
if ((next == null ? void 0 : next.type) === "semicolon") {
|
|
1029
|
-
this.consume();
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
/** Requires the next token to have the requested type. */
|
|
1033
|
-
expect(type) {
|
|
1034
|
-
const token = this.consume();
|
|
1035
|
-
if (!token || token.type !== type) {
|
|
1036
|
-
throw new Error(`Expected token ${type}.`);
|
|
1037
|
-
}
|
|
1038
|
-
return token;
|
|
1039
|
-
}
|
|
1040
|
-
/** Consumes the next token or reports truncated input. */
|
|
1041
|
-
consume() {
|
|
1042
|
-
const token = this.tokens[this.position];
|
|
1043
|
-
if (!token) {
|
|
1044
|
-
throw new Error("Unexpected end of DOT input.");
|
|
1045
|
-
}
|
|
1046
|
-
this.position++;
|
|
1047
|
-
return token;
|
|
1048
|
-
}
|
|
1049
|
-
/** Consumes a token when its type matches. */
|
|
1050
|
-
match(type) {
|
|
1051
|
-
const token = this.peek();
|
|
1052
|
-
if (token && token.type === type) {
|
|
1053
|
-
this.position++;
|
|
1054
|
-
return token;
|
|
1055
|
-
}
|
|
1056
|
-
return null;
|
|
1057
|
-
}
|
|
1058
|
-
/** Inspects a token without consuming it. */
|
|
1059
|
-
peek(offset = 0) {
|
|
1060
|
-
return this.tokens[this.position + offset] ?? null;
|
|
1061
|
-
}
|
|
1062
|
-
};
|
|
1063
|
-
IDENTIFIER_TERMINATORS = /* @__PURE__ */ new Set(["{", "}", "[", "]", "=", ";", ",", '"', "<", "#"]);
|
|
1064
|
-
}
|
|
1065
|
-
});
|
|
1066
|
-
|
|
1067
|
-
// src/dot-loader.ts
|
|
1068
|
-
var dot_loader_exports = {};
|
|
1069
|
-
__export(dot_loader_exports, {
|
|
1070
|
-
DOTLoaderWithParser: () => DOTLoaderWithParser
|
|
1071
|
-
});
|
|
1072
|
-
var DOTLoaderWithParser;
|
|
1073
|
-
var init_dot_loader = __esm({
|
|
1074
|
-
"src/dot-loader.ts"() {
|
|
1075
|
-
"use strict";
|
|
1076
|
-
init_dot_loader_types();
|
|
1077
|
-
init_parse_dot();
|
|
1078
|
-
DOTLoaderWithParser = {
|
|
1079
|
-
...DOTLoader,
|
|
1080
|
-
parse: async (data) => parseDOT(new TextDecoder().decode(data)),
|
|
1081
|
-
parseSync: (data) => parseDOT(new TextDecoder().decode(data)),
|
|
1082
|
-
parseTextSync: parseDOT
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
});
|
|
1086
|
-
|
|
1087
30
|
// dist/index.js
|
|
1088
31
|
var index_exports = {};
|
|
1089
32
|
__export(index_exports, {
|
|
1090
|
-
DOTLoader: () =>
|
|
1091
|
-
|
|
33
|
+
DOTLoader: () => DOTLoader,
|
|
34
|
+
GEXFLoader: () => GEXFLoader,
|
|
35
|
+
GraphMLLoader: () => GraphMLLoader
|
|
1092
36
|
});
|
|
1093
37
|
module.exports = __toCommonJS(index_exports);
|
|
1094
38
|
|
|
1095
39
|
// dist/graphml-loader-types.js
|
|
1096
|
-
var
|
|
1097
|
-
async function
|
|
1098
|
-
const { GraphMLLoaderWithParser
|
|
1099
|
-
return
|
|
40
|
+
var VERSION = true ? "5.0.0-beta.10" : "latest";
|
|
41
|
+
async function preload() {
|
|
42
|
+
const { GraphMLLoaderWithParser } = await import("@loaders.gl/graphs/graphml-loader");
|
|
43
|
+
return GraphMLLoaderWithParser;
|
|
1100
44
|
}
|
|
1101
|
-
var
|
|
45
|
+
var GraphMLLoader = {
|
|
1102
46
|
name: "GraphML",
|
|
1103
47
|
id: "graphml",
|
|
1104
48
|
module: "graphs",
|
|
1105
|
-
version:
|
|
49
|
+
version: VERSION,
|
|
1106
50
|
extensions: ["graphml"],
|
|
1107
51
|
mimeTypes: ["application/graphml+xml"],
|
|
1108
52
|
text: true,
|
|
1109
53
|
worker: false,
|
|
54
|
+
supportsNativeArrow: true,
|
|
1110
55
|
dataType: null,
|
|
1111
56
|
batchType: null,
|
|
1112
|
-
options: {},
|
|
1113
|
-
preload
|
|
57
|
+
options: { graphml: { shape: "arrow" } },
|
|
58
|
+
preload
|
|
1114
59
|
};
|
|
1115
60
|
|
|
1116
61
|
// dist/dot-loader-types.js
|
|
1117
|
-
var
|
|
1118
|
-
async function
|
|
1119
|
-
const { DOTLoaderWithParser
|
|
1120
|
-
return
|
|
62
|
+
var VERSION2 = true ? "5.0.0-beta.10" : "latest";
|
|
63
|
+
async function preload2() {
|
|
64
|
+
const { DOTLoaderWithParser } = await import("@loaders.gl/graphs/dot-loader");
|
|
65
|
+
return DOTLoaderWithParser;
|
|
1121
66
|
}
|
|
1122
|
-
var
|
|
67
|
+
var DOTLoader = {
|
|
1123
68
|
name: "DOT",
|
|
1124
69
|
id: "dot",
|
|
1125
70
|
module: "graphs",
|
|
1126
|
-
version:
|
|
71
|
+
version: VERSION2,
|
|
1127
72
|
extensions: ["dot", "gv"],
|
|
1128
73
|
mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
|
|
1129
74
|
text: true,
|
|
1130
75
|
worker: false,
|
|
76
|
+
supportsNativeArrow: true,
|
|
1131
77
|
dataType: null,
|
|
1132
78
|
batchType: null,
|
|
1133
|
-
options: {},
|
|
1134
|
-
preload:
|
|
79
|
+
options: { dot: { shape: "arrow" } },
|
|
80
|
+
preload: preload2
|
|
1135
81
|
};
|
|
82
|
+
|
|
83
|
+
// dist/gexf-loader-types.js
|
|
84
|
+
var VERSION3 = true ? "5.0.0-beta.10" : "latest";
|
|
85
|
+
async function preload3() {
|
|
86
|
+
const { GEXFLoaderWithParser } = await import("@loaders.gl/graphs/gexf-loader");
|
|
87
|
+
return GEXFLoaderWithParser;
|
|
88
|
+
}
|
|
89
|
+
var GEXFLoader = {
|
|
90
|
+
name: "GEXF",
|
|
91
|
+
id: "gexf",
|
|
92
|
+
module: "graphs",
|
|
93
|
+
version: VERSION3,
|
|
94
|
+
extensions: ["gexf"],
|
|
95
|
+
mimeTypes: ["application/gexf+xml"],
|
|
96
|
+
text: true,
|
|
97
|
+
worker: false,
|
|
98
|
+
supportsNativeArrow: true,
|
|
99
|
+
dataType: null,
|
|
100
|
+
batchType: null,
|
|
101
|
+
options: { gexf: { shape: "arrow" } },
|
|
102
|
+
preload: preload3
|
|
103
|
+
};
|
|
104
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
105
|
+
0 && (module.exports = {
|
|
106
|
+
DOTLoader,
|
|
107
|
+
GEXFLoader,
|
|
108
|
+
GraphMLLoader
|
|
109
|
+
});
|
|
1136
110
|
//# sourceMappingURL=index.cjs.map
|