@loaders.gl/graphs 4.5.3 → 5.0.0-alpha.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 +14 -3
- package/README.md +122 -10
- package/dist/dot-loader-types.d.ts +40 -3
- package/dist/dot-loader-types.d.ts.map +1 -1
- package/dist/dot-loader-types.js +8 -2
- package/dist/dot-loader-types.js.map +1 -1
- package/dist/dot-loader.cjs +1449 -108
- package/dist/dot-loader.cjs.map +3 -4
- 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.d.ts +53 -0
- package/dist/gexf-loader-types.d.ts.map +1 -0
- package/dist/gexf-loader-types.js +26 -0
- package/dist/gexf-loader-types.js.map +1 -0
- package/dist/gexf-loader.cjs +1304 -0
- package/dist/gexf-loader.cjs.map +6 -0
- package/dist/gexf-loader.d.ts +24 -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 +28 -0
- package/dist/graph-types.d.ts.map +1 -1
- package/dist/graphml-loader-types.d.ts +39 -3
- package/dist/graphml-loader-types.d.ts.map +1 -1
- package/dist/graphml-loader-types.js +8 -2
- package/dist/graphml-loader-types.js.map +1 -1
- package/dist/graphml-loader.cjs +1006 -61
- package/dist/graphml-loader.cjs.map +3 -4
- 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 +1452 -470
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- 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 +143 -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 +41 -24
- 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 +380 -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 +50 -27
- package/dist/lib/parse-graphml.js.map +1 -1
- package/package.json +15 -6
- package/src/dot-loader-types.ts +21 -4
- package/src/dot-loader.ts +7 -4
- package/src/dot-types.ts +7 -1
- package/src/gexf-loader-types.ts +41 -0
- package/src/gexf-loader.ts +17 -0
- package/src/gexf-types.ts +21 -0
- package/src/graph-types.ts +35 -0
- package/src/graphml-loader-types.ts +20 -4
- package/src/graphml-loader.ts +7 -4
- package/src/index.ts +11 -2
- package/src/lib/build-graph-tables.ts +208 -0
- package/src/lib/parse-dot.ts +47 -24
- package/src/lib/parse-gexf.ts +388 -0
- package/src/lib/parse-graphml.ts +86 -34
package/dist/dot-loader.cjs
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
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;
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
6
16
|
var __export = (target, all) => {
|
|
7
17
|
for (var name in all)
|
|
8
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -13,51 +23,1372 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
13
23
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
24
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
25
|
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
|
|
38
|
+
// src/dot-loader-types.ts
|
|
39
|
+
async function preload() {
|
|
40
|
+
const { DOTLoaderWithParser: DOTLoaderWithParser3 } = await Promise.resolve().then(() => (init_dot_loader(), dot_loader_exports));
|
|
41
|
+
return DOTLoaderWithParser3;
|
|
42
|
+
}
|
|
43
|
+
var VERSION, DOTLoader;
|
|
44
|
+
var init_dot_loader_types = __esm({
|
|
45
|
+
"src/dot-loader-types.ts"() {
|
|
46
|
+
"use strict";
|
|
47
|
+
VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
|
|
48
|
+
DOTLoader = {
|
|
49
|
+
name: "DOT",
|
|
50
|
+
id: "dot",
|
|
51
|
+
module: "graphs",
|
|
52
|
+
version: VERSION,
|
|
53
|
+
extensions: ["dot", "gv"],
|
|
54
|
+
mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
|
|
55
|
+
text: true,
|
|
56
|
+
worker: false,
|
|
57
|
+
dataType: null,
|
|
58
|
+
batchType: null,
|
|
59
|
+
options: { dot: { shape: "arrow-table" } },
|
|
60
|
+
preload
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ../schema-utils/src/lib/schema/convert-arrow-schema.ts
|
|
66
|
+
function convertArrowToSchema(arrowSchema) {
|
|
67
|
+
return serializeArrowSchema(arrowSchema);
|
|
68
|
+
}
|
|
69
|
+
function serializeArrowSchema(arrowSchema) {
|
|
70
|
+
return {
|
|
71
|
+
fields: arrowSchema.fields.map((arrowField) => serializeArrowField(arrowField)),
|
|
72
|
+
metadata: serializeArrowMetadata(arrowSchema.metadata)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function serializeArrowMetadata(arrowMetadata) {
|
|
76
|
+
return Object.fromEntries(arrowMetadata);
|
|
77
|
+
}
|
|
78
|
+
function serializeArrowField(field) {
|
|
79
|
+
return {
|
|
80
|
+
name: field.name,
|
|
81
|
+
type: serializeArrowType(field.type),
|
|
82
|
+
nullable: field.nullable,
|
|
83
|
+
metadata: serializeArrowMetadata(field.metadata)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function serializeArrowType(arrowType) {
|
|
87
|
+
if (isArrowViewType(arrowType, "BinaryView")) {
|
|
88
|
+
return "binary-view";
|
|
89
|
+
}
|
|
90
|
+
if (isArrowViewType(arrowType, "Utf8View")) {
|
|
91
|
+
return "utf8-view";
|
|
92
|
+
}
|
|
93
|
+
if (isOptionalArrowType(arrowType, "LargeList")) {
|
|
94
|
+
const largeListType = arrowType;
|
|
95
|
+
return {
|
|
96
|
+
type: "large-list",
|
|
97
|
+
children: [serializeArrowField(largeListType.valueField)]
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
switch (arrowType.constructor) {
|
|
101
|
+
case arrow.Null:
|
|
102
|
+
return "null";
|
|
103
|
+
case arrow.Binary:
|
|
104
|
+
return "binary";
|
|
105
|
+
case arrow.FixedSizeBinary:
|
|
106
|
+
return {
|
|
107
|
+
type: "fixed-size-binary",
|
|
108
|
+
byteWidth: arrowType.byteWidth
|
|
109
|
+
};
|
|
110
|
+
case arrow.Bool:
|
|
111
|
+
return "bool";
|
|
112
|
+
case arrow.Int:
|
|
113
|
+
const intType = arrowType;
|
|
114
|
+
return `${intType.isSigned ? "" : "u"}int${intType.bitWidth}`;
|
|
115
|
+
case arrow.Int8:
|
|
116
|
+
return "int8";
|
|
117
|
+
case arrow.Int16:
|
|
118
|
+
return "int16";
|
|
119
|
+
case arrow.Int32:
|
|
120
|
+
return "int32";
|
|
121
|
+
case arrow.Int64:
|
|
122
|
+
return "int64";
|
|
123
|
+
case arrow.Uint8:
|
|
124
|
+
return "uint8";
|
|
125
|
+
case arrow.Uint16:
|
|
126
|
+
return "uint16";
|
|
127
|
+
case arrow.Uint32:
|
|
128
|
+
return "uint32";
|
|
129
|
+
case arrow.Uint64:
|
|
130
|
+
return "uint64";
|
|
131
|
+
case arrow.Float:
|
|
132
|
+
const precision = arrowType.precision;
|
|
133
|
+
switch (precision) {
|
|
134
|
+
case arrow.Precision.HALF:
|
|
135
|
+
return "float16";
|
|
136
|
+
case arrow.Precision.SINGLE:
|
|
137
|
+
return "float32";
|
|
138
|
+
case arrow.Precision.DOUBLE:
|
|
139
|
+
return "float64";
|
|
140
|
+
default:
|
|
141
|
+
return "float16";
|
|
142
|
+
}
|
|
143
|
+
case arrow.Float16:
|
|
144
|
+
return "float16";
|
|
145
|
+
case arrow.Float32:
|
|
146
|
+
return "float32";
|
|
147
|
+
case arrow.Float64:
|
|
148
|
+
return "float64";
|
|
149
|
+
case arrow.Utf8:
|
|
150
|
+
return "utf8";
|
|
151
|
+
case arrow.Decimal:
|
|
152
|
+
const decimal = arrowType;
|
|
153
|
+
return {
|
|
154
|
+
type: "decimal",
|
|
155
|
+
bitWidth: decimal.bitWidth,
|
|
156
|
+
precision: decimal.precision,
|
|
157
|
+
scale: decimal.scale
|
|
158
|
+
};
|
|
159
|
+
case arrow.Date_:
|
|
160
|
+
const dateUnit = arrowType.unit;
|
|
161
|
+
return dateUnit === arrow.DateUnit.DAY ? "date-day" : "date-millisecond";
|
|
162
|
+
case arrow.DateDay:
|
|
163
|
+
return "date-day";
|
|
164
|
+
case arrow.DateMillisecond:
|
|
165
|
+
return "date-millisecond";
|
|
166
|
+
case arrow.Time:
|
|
167
|
+
const timeUnit = arrowType.unit;
|
|
168
|
+
switch (timeUnit) {
|
|
169
|
+
case arrow.TimeUnit.SECOND:
|
|
170
|
+
return "time-second";
|
|
171
|
+
case arrow.TimeUnit.MILLISECOND:
|
|
172
|
+
return "time-millisecond";
|
|
173
|
+
case arrow.TimeUnit.MICROSECOND:
|
|
174
|
+
return "time-microsecond";
|
|
175
|
+
case arrow.TimeUnit.NANOSECOND:
|
|
176
|
+
return "time-nanosecond";
|
|
177
|
+
default:
|
|
178
|
+
return "time-second";
|
|
179
|
+
}
|
|
180
|
+
case arrow.TimeMillisecond:
|
|
181
|
+
return "time-millisecond";
|
|
182
|
+
case arrow.TimeSecond:
|
|
183
|
+
return "time-second";
|
|
184
|
+
case arrow.TimeMicrosecond:
|
|
185
|
+
return "time-microsecond";
|
|
186
|
+
case arrow.TimeNanosecond:
|
|
187
|
+
return "time-nanosecond";
|
|
188
|
+
case arrow.Timestamp:
|
|
189
|
+
const timeStampUnit = arrowType.unit;
|
|
190
|
+
switch (timeStampUnit) {
|
|
191
|
+
case arrow.TimeUnit.SECOND:
|
|
192
|
+
return "timestamp-second";
|
|
193
|
+
case arrow.TimeUnit.MILLISECOND:
|
|
194
|
+
return "timestamp-millisecond";
|
|
195
|
+
case arrow.TimeUnit.MICROSECOND:
|
|
196
|
+
return "timestamp-microsecond";
|
|
197
|
+
case arrow.TimeUnit.NANOSECOND:
|
|
198
|
+
return "timestamp-nanosecond";
|
|
199
|
+
default:
|
|
200
|
+
return "timestamp-second";
|
|
201
|
+
}
|
|
202
|
+
case arrow.TimestampSecond:
|
|
203
|
+
return "timestamp-second";
|
|
204
|
+
case arrow.TimestampMillisecond:
|
|
205
|
+
return "timestamp-millisecond";
|
|
206
|
+
case arrow.TimestampMicrosecond:
|
|
207
|
+
return "timestamp-microsecond";
|
|
208
|
+
case arrow.TimestampNanosecond:
|
|
209
|
+
return "timestamp-nanosecond";
|
|
210
|
+
case arrow.Interval:
|
|
211
|
+
const intervalUnit = arrowType.unit;
|
|
212
|
+
switch (intervalUnit) {
|
|
213
|
+
case arrow.IntervalUnit.DAY_TIME:
|
|
214
|
+
return "interval-daytime";
|
|
215
|
+
case arrow.IntervalUnit.YEAR_MONTH:
|
|
216
|
+
return "interval-yearmonth";
|
|
217
|
+
default:
|
|
218
|
+
return "interval-daytime";
|
|
219
|
+
}
|
|
220
|
+
case arrow.IntervalDayTime:
|
|
221
|
+
return "interval-daytime";
|
|
222
|
+
case arrow.IntervalYearMonth:
|
|
223
|
+
return "interval-yearmonth";
|
|
224
|
+
case arrow.Map_:
|
|
225
|
+
const mapType = arrowType;
|
|
226
|
+
return {
|
|
227
|
+
type: "map",
|
|
228
|
+
keysSorted: mapType.keysSorted,
|
|
229
|
+
children: mapType.children.map((arrowField) => serializeArrowField(arrowField))
|
|
230
|
+
};
|
|
231
|
+
case arrow.List:
|
|
232
|
+
const listType = arrowType;
|
|
233
|
+
const listField = listType.valueField;
|
|
234
|
+
return {
|
|
235
|
+
type: "list",
|
|
236
|
+
children: [serializeArrowField(listField)]
|
|
237
|
+
};
|
|
238
|
+
case arrow.FixedSizeList:
|
|
239
|
+
const fixedSizeList = arrowType;
|
|
240
|
+
return {
|
|
241
|
+
type: "fixed-size-list",
|
|
242
|
+
listSize: fixedSizeList.listSize,
|
|
243
|
+
children: [serializeArrowField(fixedSizeList.children[0])]
|
|
244
|
+
};
|
|
245
|
+
case arrow.Struct:
|
|
246
|
+
const structType = arrowType;
|
|
247
|
+
return {
|
|
248
|
+
type: "struct",
|
|
249
|
+
children: structType.children.map((arrowField) => serializeArrowField(arrowField))
|
|
250
|
+
};
|
|
251
|
+
case arrow.SparseUnion:
|
|
252
|
+
case arrow.DenseUnion:
|
|
253
|
+
const unionType = arrowType;
|
|
254
|
+
return {
|
|
255
|
+
type: unionType instanceof arrow.DenseUnion ? "dense-union" : "sparse-union",
|
|
256
|
+
typeIds: unionType.typeIds,
|
|
257
|
+
children: unionType.children.map((arrowField) => serializeArrowField(arrowField)),
|
|
258
|
+
typeIdToChildIndex: { ...unionType.typeIdToChildIndex }
|
|
259
|
+
};
|
|
260
|
+
case arrow.Dictionary:
|
|
261
|
+
const dictionaryType = arrowType;
|
|
262
|
+
return {
|
|
263
|
+
type: "dictionary",
|
|
264
|
+
id: dictionaryType.id,
|
|
265
|
+
indices: serializeArrowDictionaryKeyType(dictionaryType.indices),
|
|
266
|
+
dictionary: serializeArrowType(dictionaryType.dictionary),
|
|
267
|
+
isOrdered: dictionaryType.isOrdered
|
|
268
|
+
};
|
|
269
|
+
default:
|
|
270
|
+
throw new Error(`arrow type not supported: ${arrowType.constructor.name}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function getOptionalArrowConstructor(typeName) {
|
|
274
|
+
return arrow[typeName];
|
|
275
|
+
}
|
|
276
|
+
function isArrowViewType(arrowType, viewTypeName) {
|
|
277
|
+
const constructor = getOptionalArrowConstructor(viewTypeName);
|
|
278
|
+
if (constructor && arrowType instanceof constructor) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
const guards = arrow.DataType;
|
|
282
|
+
const guard = viewTypeName === "BinaryView" ? guards.isBinaryView : guards.isUtf8View;
|
|
283
|
+
return Boolean(guard == null ? void 0 : guard(arrowType));
|
|
284
|
+
}
|
|
285
|
+
function isOptionalArrowType(arrowType, typeName) {
|
|
286
|
+
const constructor = getOptionalArrowConstructor(typeName);
|
|
287
|
+
return Boolean(constructor && arrowType instanceof constructor);
|
|
288
|
+
}
|
|
289
|
+
function serializeArrowDictionaryKeyType(arrowType) {
|
|
290
|
+
if (arrowType instanceof arrow.Int) {
|
|
291
|
+
const prefix = arrowType.isSigned ? "int" : "uint";
|
|
292
|
+
const keyType = `${prefix}${arrowType.bitWidth}`;
|
|
293
|
+
if (isSchemaDictionaryKeyType(keyType)) {
|
|
294
|
+
return keyType;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
switch (arrowType.constructor) {
|
|
298
|
+
case arrow.Int8:
|
|
299
|
+
return "int8";
|
|
300
|
+
case arrow.Int16:
|
|
301
|
+
return "int16";
|
|
302
|
+
case arrow.Int32:
|
|
303
|
+
return "int32";
|
|
304
|
+
case arrow.Uint8:
|
|
305
|
+
return "uint8";
|
|
306
|
+
case arrow.Uint16:
|
|
307
|
+
return "uint16";
|
|
308
|
+
case arrow.Uint32:
|
|
309
|
+
return "uint32";
|
|
310
|
+
default:
|
|
311
|
+
throw new Error(`arrow dictionary index type not supported: ${arrowType.constructor.name}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function isSchemaDictionaryKeyType(keyType) {
|
|
315
|
+
return ["int8", "int16", "int32", "uint8", "uint16", "uint32"].includes(keyType);
|
|
316
|
+
}
|
|
317
|
+
var arrow;
|
|
318
|
+
var init_convert_arrow_schema = __esm({
|
|
319
|
+
"../schema-utils/src/lib/schema/convert-arrow-schema.ts"() {
|
|
320
|
+
"use strict";
|
|
321
|
+
arrow = __toESM(require("apache-arrow"), 1);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// ../schema-utils/src/index.ts
|
|
326
|
+
var init_src = __esm({
|
|
327
|
+
"../schema-utils/src/index.ts"() {
|
|
328
|
+
"use strict";
|
|
329
|
+
init_convert_arrow_schema();
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// src/lib/build-graph-tables.ts
|
|
334
|
+
function buildGraphTables(nodes, edges, shape, declarations) {
|
|
335
|
+
if (shape === "plain-graph-data") {
|
|
336
|
+
return { shape, nodes: Array.from(nodes), edges: Array.from(edges) };
|
|
337
|
+
}
|
|
338
|
+
if (shape !== "arrow-table" && shape !== "object-row-table") {
|
|
339
|
+
throw new Error(`Unsupported graph shape: ${shape}`);
|
|
340
|
+
}
|
|
341
|
+
const nodeTable = buildGraphTable(nodes, false, shape, declarations == null ? void 0 : declarations.nodes);
|
|
342
|
+
const edgeTable = buildGraphTable(edges, true, shape, declarations == null ? void 0 : declarations.edges);
|
|
343
|
+
return {
|
|
344
|
+
shape: "tables",
|
|
345
|
+
tables: [
|
|
346
|
+
{ name: "nodes", table: nodeTable },
|
|
347
|
+
{ name: "edges", table: edgeTable }
|
|
348
|
+
]
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function buildGraphTable(records, isEdge, shape, declarations) {
|
|
352
|
+
const columnNames = isEdge ? ["id", "sourceId", "targetId", "directed", "label", "attributes"] : ["id", "label", "attributes"];
|
|
353
|
+
const columns = new Map(columnNames.map((name) => [name, []]));
|
|
354
|
+
for (const record of records) {
|
|
355
|
+
for (const name of columnNames) {
|
|
356
|
+
const value = record[name];
|
|
357
|
+
columns.get(name).push(
|
|
358
|
+
name === "id" || name === "sourceId" || name === "targetId" ? String(value) : value ?? null
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (shape === "object-row-table") {
|
|
363
|
+
return {
|
|
364
|
+
shape,
|
|
365
|
+
data: columns.get("id").map(
|
|
366
|
+
(_, index) => Object.fromEntries(columnNames.map((name) => [name, columns.get(name)[index]]))
|
|
367
|
+
)
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
const vectors = /* @__PURE__ */ Object.create(null);
|
|
371
|
+
for (const [name, values] of columns) {
|
|
372
|
+
const type = name === "attributes" ? inferAttributeType(values, declarations) : name === "directed" ? new import_apache_arrow.Bool() : new import_apache_arrow.Utf8();
|
|
373
|
+
vectors[name] = (0, import_apache_arrow.vectorFromArray)(
|
|
374
|
+
values.map((value) => normalizeValue(value, type)),
|
|
375
|
+
type
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
const data = new import_apache_arrow.Table(vectors);
|
|
379
|
+
return { shape, schema: convertArrowToSchema(data.schema), data };
|
|
380
|
+
}
|
|
381
|
+
function inferAttributeType(values, declarations) {
|
|
382
|
+
const names = new Set(declarations == null ? void 0 : declarations.keys());
|
|
383
|
+
for (const value of values) {
|
|
384
|
+
if (value && typeof value === "object") {
|
|
385
|
+
for (const name of Object.keys(value)) {
|
|
386
|
+
names.add(name);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return new import_apache_arrow.Struct(
|
|
391
|
+
Array.from(names, (name) => {
|
|
392
|
+
const fieldValues = values.map(
|
|
393
|
+
(value) => (value == null ? void 0 : value[name]) ?? null
|
|
394
|
+
);
|
|
395
|
+
return new import_apache_arrow.Field(name, inferValueType(fieldValues, declarations == null ? void 0 : declarations.get(name)), true);
|
|
396
|
+
})
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
function inferValueType(values, declaration) {
|
|
400
|
+
const present = values.filter((value) => value !== null && value !== void 0);
|
|
401
|
+
if (declaration && typeof declaration === "object") {
|
|
402
|
+
if (!present.every((value) => Array.isArray(value))) return new import_apache_arrow.Utf8();
|
|
403
|
+
return new import_apache_arrow.List(
|
|
404
|
+
new import_apache_arrow.Field(
|
|
405
|
+
"item",
|
|
406
|
+
inferValueType(
|
|
407
|
+
present.flatMap((value) => value),
|
|
408
|
+
declaration.list
|
|
409
|
+
),
|
|
410
|
+
true
|
|
411
|
+
)
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
if (declaration) {
|
|
415
|
+
const declaredTypes = {
|
|
416
|
+
boolean: new import_apache_arrow.Bool(),
|
|
417
|
+
int: new import_apache_arrow.Int32(),
|
|
418
|
+
long: new import_apache_arrow.Int64(),
|
|
419
|
+
float: new import_apache_arrow.Float32(),
|
|
420
|
+
double: new import_apache_arrow.Float64(),
|
|
421
|
+
string: new import_apache_arrow.Utf8()
|
|
422
|
+
};
|
|
423
|
+
const valid = present.every((value) => {
|
|
424
|
+
switch (declaration) {
|
|
425
|
+
case "boolean":
|
|
426
|
+
return typeof value === "boolean";
|
|
427
|
+
case "int":
|
|
428
|
+
return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
|
|
429
|
+
case "long":
|
|
430
|
+
return typeof value === "bigint" && value >= -(2n ** 63n) && value < 2n ** 63n;
|
|
431
|
+
case "float":
|
|
432
|
+
case "double":
|
|
433
|
+
return typeof value === "number";
|
|
434
|
+
case "string":
|
|
435
|
+
return typeof value === "string";
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
return valid ? declaredTypes[declaration] : new import_apache_arrow.Utf8();
|
|
439
|
+
}
|
|
440
|
+
if (present.length && present.every((value) => typeof value === "boolean")) return new import_apache_arrow.Bool();
|
|
441
|
+
if (present.length && present.every((value) => typeof value === "number")) return new import_apache_arrow.Float64();
|
|
442
|
+
if (present.length && present.every((value) => Array.isArray(value))) {
|
|
443
|
+
return new import_apache_arrow.List(
|
|
444
|
+
new import_apache_arrow.Field("item", inferValueType(present.flatMap((value) => value)), true)
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
if (present.length && present.every((value) => typeof value === "object" && !Array.isArray(value))) {
|
|
448
|
+
return inferAttributeType(present);
|
|
449
|
+
}
|
|
450
|
+
return new import_apache_arrow.Utf8();
|
|
451
|
+
}
|
|
452
|
+
function normalizeValue(value, type) {
|
|
453
|
+
if (value === null || value === void 0) return null;
|
|
454
|
+
if (type instanceof import_apache_arrow.Struct) {
|
|
455
|
+
return Object.fromEntries(
|
|
456
|
+
type.children.map((field) => [
|
|
457
|
+
field.name,
|
|
458
|
+
normalizeValue(value[field.name], field.type)
|
|
459
|
+
])
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
if (type instanceof import_apache_arrow.List)
|
|
463
|
+
return value.map((item) => normalizeValue(item, type.valueType));
|
|
464
|
+
if (type instanceof import_apache_arrow.Utf8 && typeof value !== "string") {
|
|
465
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
466
|
+
}
|
|
467
|
+
return value;
|
|
468
|
+
}
|
|
469
|
+
var import_apache_arrow;
|
|
470
|
+
var init_build_graph_tables = __esm({
|
|
471
|
+
"src/lib/build-graph-tables.ts"() {
|
|
472
|
+
"use strict";
|
|
473
|
+
import_apache_arrow = require("apache-arrow");
|
|
474
|
+
init_src();
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// src/lib/parse-dot.ts
|
|
479
|
+
function parseDOT(input, shape = "plain-graph-data") {
|
|
480
|
+
const parsed = parseDOTDocument(input);
|
|
481
|
+
return {
|
|
482
|
+
...buildGraphTables(iterateNodes(parsed), iterateEdges(parsed), shape),
|
|
483
|
+
metadata: {
|
|
484
|
+
id: parsed.id,
|
|
485
|
+
directed: parsed.directed,
|
|
486
|
+
strict: parsed.strict,
|
|
487
|
+
attributes: { ...parsed.graphAttributes },
|
|
488
|
+
subgraphs: Array.from(parsed.subgraphs.values(), (subgraph) => ({
|
|
489
|
+
...subgraph,
|
|
490
|
+
attributes: { ...subgraph.attributes }
|
|
491
|
+
}))
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function* iterateNodes(parsed) {
|
|
496
|
+
for (const node of parsed.nodes.values()) {
|
|
497
|
+
yield {
|
|
498
|
+
id: node.id,
|
|
499
|
+
...typeof node.attributes.label === "string" ? { label: node.attributes.label } : {},
|
|
500
|
+
attributes: {
|
|
501
|
+
...node.attributes,
|
|
502
|
+
...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) => describeSubgraph(id, parsed.subgraphs)) } : {}
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function* iterateEdges(parsed) {
|
|
508
|
+
for (const edge of parsed.edges) {
|
|
509
|
+
yield {
|
|
510
|
+
id: edge.id,
|
|
511
|
+
sourceId: edge.sourceId,
|
|
512
|
+
targetId: edge.targetId,
|
|
513
|
+
directed: edge.directed,
|
|
514
|
+
...typeof edge.attributes.label === "string" ? { label: edge.attributes.label } : {},
|
|
515
|
+
attributes: {
|
|
516
|
+
...edge.attributes,
|
|
517
|
+
...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) => describeSubgraph(id, parsed.subgraphs)) } : {}
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function describeSubgraph(id, descriptors) {
|
|
523
|
+
const subgraph = descriptors.get(id);
|
|
524
|
+
return {
|
|
525
|
+
id,
|
|
526
|
+
attributes: { ...subgraph.attributes },
|
|
527
|
+
parentId: subgraph.parentId
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function parseDOTDocument(input) {
|
|
531
|
+
const parser = new DOTParser(tokenize(input));
|
|
532
|
+
return parser.parse();
|
|
533
|
+
}
|
|
534
|
+
function tokenize(input) {
|
|
535
|
+
const tokens = [];
|
|
536
|
+
let index = 0;
|
|
537
|
+
while (index < input.length) {
|
|
538
|
+
const { token, nextIndex } = readNextToken(input, index);
|
|
539
|
+
if (nextIndex <= index) {
|
|
540
|
+
throw new Error(`Tokenizer did not advance at position ${index}.`);
|
|
541
|
+
}
|
|
542
|
+
if (token) {
|
|
543
|
+
tokens.push(token);
|
|
544
|
+
}
|
|
545
|
+
index = nextIndex;
|
|
546
|
+
}
|
|
547
|
+
return tokens;
|
|
548
|
+
}
|
|
549
|
+
function readNextToken(input, index) {
|
|
550
|
+
if (index >= input.length) {
|
|
551
|
+
return { token: null, nextIndex: input.length };
|
|
552
|
+
}
|
|
553
|
+
const character = input[index];
|
|
554
|
+
if (isWhitespace(character)) {
|
|
555
|
+
return { token: null, nextIndex: index + 1 };
|
|
556
|
+
}
|
|
557
|
+
const commentEnd = skipComment(input, index);
|
|
558
|
+
if (commentEnd !== null) {
|
|
559
|
+
return { token: null, nextIndex: commentEnd };
|
|
560
|
+
}
|
|
561
|
+
const arrowToken = readArrowToken(input, index);
|
|
562
|
+
if (arrowToken) {
|
|
563
|
+
return arrowToken;
|
|
564
|
+
}
|
|
565
|
+
const punctuation = readPunctuationToken(character);
|
|
566
|
+
if (punctuation) {
|
|
567
|
+
return { token: punctuation, nextIndex: index + 1 };
|
|
568
|
+
}
|
|
569
|
+
if (character === '"') {
|
|
570
|
+
const { value, nextIndex } = readQuotedString(input, index + 1);
|
|
571
|
+
return { token: { type: "string", value }, nextIndex };
|
|
572
|
+
}
|
|
573
|
+
if (character === "<") {
|
|
574
|
+
const { value, nextIndex } = readHtmlString(input, index + 1);
|
|
575
|
+
return { token: { type: "html", value }, nextIndex };
|
|
576
|
+
}
|
|
577
|
+
const identifier = readIdentifier(input, index);
|
|
578
|
+
if (identifier.value) {
|
|
579
|
+
return {
|
|
580
|
+
token: { type: "identifier", value: identifier.value },
|
|
581
|
+
nextIndex: identifier.nextIndex
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
throw new Error(`Unexpected token at position ${index}.`);
|
|
585
|
+
}
|
|
586
|
+
function skipComment(input, index) {
|
|
587
|
+
const character = input[index];
|
|
588
|
+
if (character === "/") {
|
|
589
|
+
const next = input[index + 1];
|
|
590
|
+
if (next === "/") {
|
|
591
|
+
return skipLineComment(input, index + 2);
|
|
592
|
+
}
|
|
593
|
+
if (next === "*") {
|
|
594
|
+
return skipBlockComment(input, index + 2);
|
|
595
|
+
}
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
if (character === "#") {
|
|
599
|
+
return skipLineComment(input, index + 1);
|
|
600
|
+
}
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
function skipLineComment(input, startIndex) {
|
|
604
|
+
let cursor = startIndex;
|
|
605
|
+
while (cursor < input.length && !isLineBreak(input[cursor])) {
|
|
606
|
+
cursor++;
|
|
607
|
+
}
|
|
608
|
+
return cursor;
|
|
609
|
+
}
|
|
610
|
+
function skipBlockComment(input, startIndex) {
|
|
611
|
+
let cursor = startIndex;
|
|
612
|
+
while (cursor < input.length) {
|
|
613
|
+
if (input[cursor] === "*" && input[cursor + 1] === "/") {
|
|
614
|
+
return cursor + 2;
|
|
615
|
+
}
|
|
616
|
+
cursor++;
|
|
617
|
+
}
|
|
618
|
+
throw new Error("Unterminated block comment in DOT source.");
|
|
619
|
+
}
|
|
620
|
+
function readArrowToken(input, index) {
|
|
621
|
+
const next = input[index + 1];
|
|
622
|
+
if (input[index] === "-" && next === "-") {
|
|
623
|
+
return { token: { type: "arrow", value: "--" }, nextIndex: index + 2 };
|
|
624
|
+
}
|
|
625
|
+
if (input[index] === "-" && next === ">") {
|
|
626
|
+
return { token: { type: "arrow", value: "->" }, nextIndex: index + 2 };
|
|
627
|
+
}
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
function readPunctuationToken(character) {
|
|
631
|
+
switch (character) {
|
|
632
|
+
case "{":
|
|
633
|
+
return { type: "lbrace", value: character };
|
|
634
|
+
case "}":
|
|
635
|
+
return { type: "rbrace", value: character };
|
|
636
|
+
case "[":
|
|
637
|
+
return { type: "lbrack", value: character };
|
|
638
|
+
case "]":
|
|
639
|
+
return { type: "rbrack", value: character };
|
|
640
|
+
case "=":
|
|
641
|
+
return { type: "equals", value: character };
|
|
642
|
+
case ",":
|
|
643
|
+
return { type: "comma", value: character };
|
|
644
|
+
case ";":
|
|
645
|
+
return { type: "semicolon", value: character };
|
|
646
|
+
default:
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function readQuotedString(input, startIndex) {
|
|
651
|
+
let value = "";
|
|
652
|
+
let index = startIndex;
|
|
653
|
+
while (index < input.length) {
|
|
654
|
+
const character = input[index];
|
|
655
|
+
if (character === '"') {
|
|
656
|
+
return { value, nextIndex: index + 1 };
|
|
657
|
+
}
|
|
658
|
+
if (character === "\\") {
|
|
659
|
+
const escape = readEscapedCharacter(input, index + 1);
|
|
660
|
+
value += escape.value;
|
|
661
|
+
index = escape.nextIndex;
|
|
662
|
+
} else {
|
|
663
|
+
value += character;
|
|
664
|
+
index++;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
throw new Error("Unterminated string literal in DOT source.");
|
|
668
|
+
}
|
|
669
|
+
function readEscapedCharacter(input, startIndex) {
|
|
670
|
+
const next = input[startIndex];
|
|
671
|
+
switch (next) {
|
|
672
|
+
case "\n":
|
|
673
|
+
return { value: "", nextIndex: startIndex + 1 };
|
|
674
|
+
case "\r":
|
|
675
|
+
return { value: "", nextIndex: startIndex + (input[startIndex + 1] === "\n" ? 2 : 1) };
|
|
676
|
+
case "n":
|
|
677
|
+
case "l":
|
|
678
|
+
case "L":
|
|
679
|
+
return { value: "\n", nextIndex: startIndex + 1 };
|
|
680
|
+
case "t":
|
|
681
|
+
return { value: " ", nextIndex: startIndex + 1 };
|
|
682
|
+
case "r":
|
|
683
|
+
return { value: "\r", nextIndex: startIndex + 1 };
|
|
684
|
+
case '"':
|
|
685
|
+
return { value: '"', nextIndex: startIndex + 1 };
|
|
686
|
+
case "\\":
|
|
687
|
+
return { value: "\\", nextIndex: startIndex + 1 };
|
|
688
|
+
default: {
|
|
689
|
+
if (typeof next === "undefined") {
|
|
690
|
+
throw new Error("Unterminated escape sequence in DOT source.");
|
|
691
|
+
}
|
|
692
|
+
return { value: `\\${next}`, nextIndex: startIndex + 1 };
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
function readHtmlString(input, startIndex) {
|
|
697
|
+
let value = "<";
|
|
698
|
+
let depth = 1;
|
|
699
|
+
let index = startIndex;
|
|
700
|
+
while (index < input.length) {
|
|
701
|
+
const character = input[index];
|
|
702
|
+
value += character;
|
|
703
|
+
if (character === "<") {
|
|
704
|
+
depth++;
|
|
705
|
+
} else if (character === ">") {
|
|
706
|
+
depth--;
|
|
707
|
+
if (depth === 0) {
|
|
708
|
+
return { value, nextIndex: index + 1 };
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
index++;
|
|
712
|
+
}
|
|
713
|
+
throw new Error("Unterminated HTML-like string literal in DOT source.");
|
|
714
|
+
}
|
|
715
|
+
function readIdentifier(input, startIndex) {
|
|
716
|
+
let index = startIndex;
|
|
717
|
+
let value = "";
|
|
718
|
+
while (index < input.length && !isIdentifierTerminator(input, index)) {
|
|
719
|
+
value += input[index];
|
|
720
|
+
index++;
|
|
721
|
+
}
|
|
722
|
+
if (value.includes(":")) {
|
|
723
|
+
throw new Error("DOT node ports are not supported; quote identifiers containing colons.");
|
|
724
|
+
}
|
|
725
|
+
return { value, nextIndex: index };
|
|
726
|
+
}
|
|
727
|
+
function isIdentifierTerminator(input, index) {
|
|
728
|
+
const character = input[index];
|
|
729
|
+
if (isWhitespace(character) || IDENTIFIER_TERMINATORS.has(character)) {
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
if (isArrowOperatorStart(input, index)) {
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
735
|
+
if (isCommentStart(input, index)) {
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
function isArrowOperatorStart(input, index) {
|
|
741
|
+
if (input[index] !== "-") {
|
|
742
|
+
return false;
|
|
743
|
+
}
|
|
744
|
+
const next = input[index + 1];
|
|
745
|
+
return next === "-" || next === ">";
|
|
746
|
+
}
|
|
747
|
+
function isCommentStart(input, index) {
|
|
748
|
+
if (input[index] !== "/") {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
const next = input[index + 1];
|
|
752
|
+
return next === "/" || next === "*";
|
|
753
|
+
}
|
|
754
|
+
function isWhitespace(character) {
|
|
755
|
+
return character === " " || character === "\n" || character === "\r" || character === " " || character === "\f";
|
|
756
|
+
}
|
|
757
|
+
function isLineBreak(character) {
|
|
758
|
+
return character === "\n" || character === "\r";
|
|
759
|
+
}
|
|
760
|
+
function isKeyword(token, keyword) {
|
|
761
|
+
return token.type === "identifier" && token.value.toLowerCase() === keyword.toLowerCase();
|
|
762
|
+
}
|
|
763
|
+
function isGraphType(token) {
|
|
764
|
+
return isKeyword(token, "graph") || isKeyword(token, "digraph");
|
|
765
|
+
}
|
|
766
|
+
function isIdentifierLike(token) {
|
|
767
|
+
return token.type === "identifier" || token.type === "string" || token.type === "html";
|
|
768
|
+
}
|
|
769
|
+
function parseIdentifierValue(token) {
|
|
770
|
+
return token.value;
|
|
771
|
+
}
|
|
772
|
+
function parseAttributeValue(token) {
|
|
773
|
+
if (token.type === "string" || token.type === "html") {
|
|
774
|
+
return token.value;
|
|
775
|
+
}
|
|
776
|
+
if (token.type === "identifier") {
|
|
777
|
+
const numeric = Number(token.value);
|
|
778
|
+
if (!Number.isNaN(numeric)) {
|
|
779
|
+
return numeric;
|
|
780
|
+
}
|
|
781
|
+
return token.value;
|
|
782
|
+
}
|
|
783
|
+
throw new Error("Invalid attribute value in DOT input.");
|
|
784
|
+
}
|
|
785
|
+
function deriveEdgeId(attributes, sourceId, targetId, counter) {
|
|
786
|
+
const candidate = attributes.id ?? attributes.Id ?? attributes.ID;
|
|
787
|
+
if (typeof candidate === "string" || typeof candidate === "number") {
|
|
788
|
+
return String(candidate);
|
|
789
|
+
}
|
|
790
|
+
return `${String(sourceId)}-${String(targetId)}-${counter}`;
|
|
791
|
+
}
|
|
792
|
+
function deriveDirectedFlag(attributes, defaultDirected) {
|
|
793
|
+
const candidate = attributes.directed;
|
|
794
|
+
if (typeof candidate === "boolean") {
|
|
795
|
+
return candidate;
|
|
796
|
+
}
|
|
797
|
+
const directionAttribute = attributes.dir;
|
|
798
|
+
if (typeof directionAttribute === "string") {
|
|
799
|
+
const normalized = directionAttribute.toLowerCase();
|
|
800
|
+
if (normalized === "none") {
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
return true;
|
|
804
|
+
}
|
|
805
|
+
return defaultDirected;
|
|
806
|
+
}
|
|
807
|
+
var DOTParser, IDENTIFIER_TERMINATORS;
|
|
808
|
+
var init_parse_dot = __esm({
|
|
809
|
+
"src/lib/parse-dot.ts"() {
|
|
810
|
+
"use strict";
|
|
811
|
+
init_build_graph_tables();
|
|
812
|
+
DOTParser = class {
|
|
813
|
+
/** Tokens for DOT parsing. */
|
|
814
|
+
tokens;
|
|
815
|
+
/** Position for DOT parsing. */
|
|
816
|
+
position = 0;
|
|
817
|
+
/** Accumulated graph records and attributes. */
|
|
818
|
+
result = {
|
|
819
|
+
directed: false,
|
|
820
|
+
strict: false,
|
|
821
|
+
graphAttributes: /* @__PURE__ */ Object.create(null),
|
|
822
|
+
nodes: /* @__PURE__ */ new Map(),
|
|
823
|
+
edges: [],
|
|
824
|
+
subgraphs: /* @__PURE__ */ new Map()
|
|
825
|
+
};
|
|
826
|
+
/** Scopes for DOT parsing. */
|
|
827
|
+
scopes = [
|
|
828
|
+
{
|
|
829
|
+
nodeDefaults: /* @__PURE__ */ Object.create(null),
|
|
830
|
+
edgeDefaults: /* @__PURE__ */ Object.create(null),
|
|
831
|
+
graphAttributes: /* @__PURE__ */ Object.create(null)
|
|
832
|
+
}
|
|
833
|
+
];
|
|
834
|
+
/** Subgraph counter for DOT parsing. */
|
|
835
|
+
subgraphCounter = 0;
|
|
836
|
+
/** Edge counter for DOT parsing. */
|
|
837
|
+
edgeCounter = 0;
|
|
838
|
+
/** Edge lookup used to coalesce parallel edges in strict graphs. */
|
|
839
|
+
strictEdges = /* @__PURE__ */ new Map();
|
|
840
|
+
/** Persistent attributes and defaults for reopened named subgraphs. */
|
|
841
|
+
subgraphScopes = /* @__PURE__ */ new Map();
|
|
842
|
+
/** Explicit names reserved so anonymous subgraph IDs cannot collide with them. */
|
|
843
|
+
namedSubgraphIds = /* @__PURE__ */ new Set();
|
|
844
|
+
/** Initializes the token stream. */
|
|
845
|
+
constructor(tokens) {
|
|
846
|
+
this.tokens = tokens;
|
|
847
|
+
for (let index = 0; index < tokens.length - 1; index++) {
|
|
848
|
+
if (isKeyword(tokens[index], "subgraph") && isIdentifierLike(tokens[index + 1])) {
|
|
849
|
+
this.namedSubgraphIds.add(tokens[index + 1].value);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
/** Parses one complete DOT document. */
|
|
854
|
+
parse() {
|
|
855
|
+
this.parseGraph();
|
|
856
|
+
this.consumeOptionalSemicolon();
|
|
857
|
+
if (this.peek()) {
|
|
858
|
+
throw new Error("Unexpected content after DOT graph.");
|
|
859
|
+
}
|
|
860
|
+
return this.result;
|
|
861
|
+
}
|
|
862
|
+
/** Reads graph identity, declaration, and statements. */
|
|
863
|
+
parseGraph() {
|
|
864
|
+
const strictToken = this.peek();
|
|
865
|
+
if (strictToken && isKeyword(strictToken, "strict")) {
|
|
866
|
+
this.consume();
|
|
867
|
+
this.result.strict = true;
|
|
868
|
+
}
|
|
869
|
+
const typeToken = this.peek();
|
|
870
|
+
if (!typeToken || !isGraphType(typeToken)) {
|
|
871
|
+
throw new Error("DOT graph must start with graph or digraph keyword.");
|
|
872
|
+
}
|
|
873
|
+
this.consume();
|
|
874
|
+
this.result.directed = isKeyword(typeToken, "digraph");
|
|
875
|
+
const idToken = this.peek();
|
|
876
|
+
if (idToken && isIdentifierLike(idToken)) {
|
|
877
|
+
this.result.id = parseIdentifierValue(this.consume());
|
|
878
|
+
}
|
|
879
|
+
this.expect("lbrace");
|
|
880
|
+
while (!this.match("rbrace")) {
|
|
881
|
+
if (!this.parseStatement()) {
|
|
882
|
+
throw new Error("Expected closing brace in DOT graph.");
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
this.result.graphAttributes = { ...this.scopes[0].graphAttributes };
|
|
886
|
+
}
|
|
887
|
+
/** Dispatches a graph statement. */
|
|
888
|
+
parseStatement() {
|
|
889
|
+
if (this.consumeSemicolonIfPresent()) {
|
|
890
|
+
return true;
|
|
891
|
+
}
|
|
892
|
+
const token = this.peek();
|
|
893
|
+
if (!token) {
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
if (this.tryParseSubgraphStatement(token)) {
|
|
897
|
+
return true;
|
|
898
|
+
}
|
|
899
|
+
if (this.tryParseKeywordStatement(token)) {
|
|
900
|
+
return true;
|
|
901
|
+
}
|
|
902
|
+
if (this.tryParseAssignmentStatement(token)) {
|
|
903
|
+
return true;
|
|
904
|
+
}
|
|
905
|
+
if (isIdentifierLike(token)) {
|
|
906
|
+
this.parseNodeOrEdgeStatement();
|
|
907
|
+
this.consumeOptionalSemicolon();
|
|
908
|
+
return true;
|
|
909
|
+
}
|
|
910
|
+
throw new Error(`Unexpected token: ${token.value}`);
|
|
911
|
+
}
|
|
912
|
+
/** Consumes an empty statement. */
|
|
913
|
+
consumeSemicolonIfPresent() {
|
|
914
|
+
const next = this.peek();
|
|
915
|
+
if ((next == null ? void 0 : next.type) === "semicolon") {
|
|
916
|
+
this.consume();
|
|
917
|
+
return true;
|
|
918
|
+
}
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
/** Reads a standalone subgraph statement. */
|
|
922
|
+
tryParseSubgraphStatement(token) {
|
|
923
|
+
if (token.type !== "lbrace" && !isKeyword(token, "subgraph")) {
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
this.parseSubgraph();
|
|
927
|
+
return true;
|
|
928
|
+
}
|
|
929
|
+
/** Applies graph, node, or edge defaults. */
|
|
930
|
+
tryParseKeywordStatement(token) {
|
|
931
|
+
if (!(isKeyword(token, "graph") || isKeyword(token, "node") || isKeyword(token, "edge"))) {
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
this.consume();
|
|
935
|
+
const explicitAttributes = this.parseAttributeList();
|
|
936
|
+
if (isKeyword(token, "graph")) {
|
|
937
|
+
Object.assign(this.currentScope().graphAttributes, explicitAttributes);
|
|
938
|
+
} else if (isKeyword(token, "node")) {
|
|
939
|
+
Object.assign(this.currentScope().nodeDefaults, explicitAttributes);
|
|
940
|
+
} else {
|
|
941
|
+
Object.assign(this.currentScope().edgeDefaults, explicitAttributes);
|
|
942
|
+
}
|
|
943
|
+
this.consumeOptionalSemicolon();
|
|
944
|
+
return true;
|
|
945
|
+
}
|
|
946
|
+
/** Reads a graph attribute assignment. */
|
|
947
|
+
tryParseAssignmentStatement(token) {
|
|
948
|
+
if (!isIdentifierLike(token)) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
const next = this.peek(1);
|
|
952
|
+
if ((next == null ? void 0 : next.type) !== "equals") {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
const key = parseIdentifierValue(this.consume());
|
|
956
|
+
this.consume();
|
|
957
|
+
const valueToken = this.consume();
|
|
958
|
+
const value = parseAttributeValue(valueToken);
|
|
959
|
+
this.currentScope().graphAttributes[key] = value;
|
|
960
|
+
this.consumeOptionalSemicolon();
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
/** Reads a node statement or chained edges. */
|
|
964
|
+
parseNodeOrEdgeStatement() {
|
|
965
|
+
const first = parseIdentifierValue(this.consume());
|
|
966
|
+
const references = [first];
|
|
967
|
+
const operators = [];
|
|
968
|
+
let operatorToken = this.match("arrow");
|
|
969
|
+
while (operatorToken) {
|
|
970
|
+
operators.push(operatorToken.value);
|
|
971
|
+
const referenceToken = this.consume();
|
|
972
|
+
if (!isIdentifierLike(referenceToken)) {
|
|
973
|
+
throw new Error("Expected node identifier in edge statement.");
|
|
974
|
+
}
|
|
975
|
+
references.push(parseIdentifierValue(referenceToken));
|
|
976
|
+
operatorToken = this.match("arrow");
|
|
977
|
+
}
|
|
978
|
+
if (operators.length === 0) {
|
|
979
|
+
const explicitAttributes2 = this.parseAttributeList();
|
|
980
|
+
this.addNode(first, explicitAttributes2);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
const explicitAttributes = this.parseAttributeList();
|
|
984
|
+
this.addEdgeChain(references, operators, explicitAttributes);
|
|
985
|
+
}
|
|
986
|
+
/** Merges explicit attributes into a node. */
|
|
987
|
+
addNode(id, explicitAttributes) {
|
|
988
|
+
const membership = this.getCurrentSubgraphChain();
|
|
989
|
+
const node = this.ensureNode(id, membership);
|
|
990
|
+
node.attributes = { ...node.attributes, ...explicitAttributes };
|
|
991
|
+
}
|
|
992
|
+
/** Expands an edge chain into node and edge records. */
|
|
993
|
+
addEdgeChain(nodes, operators, explicitAttributes) {
|
|
994
|
+
const membership = this.getCurrentSubgraphChain();
|
|
995
|
+
const defaults = this.currentScope().edgeDefaults;
|
|
996
|
+
const attributes = { ...defaults, ...explicitAttributes };
|
|
997
|
+
for (let index = 0; index < nodes.length - 1; index++) {
|
|
998
|
+
const sourceId = nodes[index];
|
|
999
|
+
const targetId = nodes[index + 1];
|
|
1000
|
+
const operator = operators[index];
|
|
1001
|
+
const directed = operator === "->";
|
|
1002
|
+
if (directed !== this.result.directed) {
|
|
1003
|
+
throw new Error("DOT edge operator must match graph or digraph declaration.");
|
|
1004
|
+
}
|
|
1005
|
+
const edgeId = deriveEdgeId(attributes, sourceId, targetId, ++this.edgeCounter);
|
|
1006
|
+
const edgeAttributes = { ...attributes };
|
|
1007
|
+
this.ensureNode(sourceId, membership);
|
|
1008
|
+
this.ensureNode(targetId, membership);
|
|
1009
|
+
const strictKey = JSON.stringify(
|
|
1010
|
+
directed ? [sourceId, targetId] : [sourceId, targetId].sort()
|
|
1011
|
+
);
|
|
1012
|
+
const existingEdge = this.result.strict ? this.strictEdges.get(strictKey) : void 0;
|
|
1013
|
+
if (existingEdge) {
|
|
1014
|
+
existingEdge.attributes = { ...existingEdge.attributes, ...explicitAttributes };
|
|
1015
|
+
const explicitId = explicitAttributes.id ?? explicitAttributes.Id ?? explicitAttributes.ID;
|
|
1016
|
+
if (typeof explicitId === "string" || typeof explicitId === "number") {
|
|
1017
|
+
existingEdge.id = String(explicitId);
|
|
1018
|
+
}
|
|
1019
|
+
existingEdge.directed = deriveDirectedFlag(existingEdge.attributes, directed);
|
|
1020
|
+
existingEdge.subgraphs = Array.from(/* @__PURE__ */ new Set([...existingEdge.subgraphs, ...membership]));
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
const directedOverride = deriveDirectedFlag(edgeAttributes, directed);
|
|
1024
|
+
const edge = {
|
|
1025
|
+
id: edgeId,
|
|
1026
|
+
sourceId,
|
|
1027
|
+
targetId,
|
|
1028
|
+
directed: directedOverride,
|
|
1029
|
+
attributes: edgeAttributes,
|
|
1030
|
+
subgraphs: membership
|
|
1031
|
+
};
|
|
1032
|
+
this.result.edges.push(edge);
|
|
1033
|
+
if (this.result.strict) {
|
|
1034
|
+
this.strictEdges.set(strictKey, edge);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
/** Reads a nested scope with inherited defaults. */
|
|
1039
|
+
parseSubgraph() {
|
|
1040
|
+
let idToken = this.peek();
|
|
1041
|
+
let subgraphId;
|
|
1042
|
+
if (idToken && isKeyword(idToken, "subgraph")) {
|
|
1043
|
+
this.consume();
|
|
1044
|
+
idToken = this.peek();
|
|
1045
|
+
}
|
|
1046
|
+
if (idToken && isIdentifierLike(idToken)) {
|
|
1047
|
+
subgraphId = parseIdentifierValue(this.consume());
|
|
1048
|
+
} else {
|
|
1049
|
+
do {
|
|
1050
|
+
subgraphId = `subgraph_${++this.subgraphCounter}`;
|
|
1051
|
+
} while (this.namedSubgraphIds.has(subgraphId));
|
|
1052
|
+
}
|
|
1053
|
+
this.expect("lbrace");
|
|
1054
|
+
const parentId = this.findCurrentSubgraphId();
|
|
1055
|
+
let context = this.subgraphScopes.get(subgraphId);
|
|
1056
|
+
if (!context) {
|
|
1057
|
+
context = {
|
|
1058
|
+
id: subgraphId,
|
|
1059
|
+
nodeDefaults: Object.assign(/* @__PURE__ */ Object.create(null), this.currentScope().nodeDefaults),
|
|
1060
|
+
edgeDefaults: Object.assign(/* @__PURE__ */ Object.create(null), this.currentScope().edgeDefaults),
|
|
1061
|
+
graphAttributes: /* @__PURE__ */ Object.create(null)
|
|
1062
|
+
};
|
|
1063
|
+
this.subgraphScopes.set(subgraphId, context);
|
|
1064
|
+
this.result.subgraphs.set(subgraphId, {
|
|
1065
|
+
id: subgraphId,
|
|
1066
|
+
attributes: context.graphAttributes,
|
|
1067
|
+
parentId
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
this.scopes.push(context);
|
|
1071
|
+
let shouldContinue = true;
|
|
1072
|
+
while (shouldContinue) {
|
|
1073
|
+
if (this.match("rbrace")) {
|
|
1074
|
+
break;
|
|
1075
|
+
}
|
|
1076
|
+
shouldContinue = this.parseStatement();
|
|
1077
|
+
if (!shouldContinue) {
|
|
1078
|
+
throw new Error("Expected closing brace in DOT subgraph.");
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
this.scopes.pop();
|
|
1082
|
+
}
|
|
1083
|
+
/** Reads repeated attribute lists. */
|
|
1084
|
+
parseAttributeList() {
|
|
1085
|
+
var _a, _b;
|
|
1086
|
+
const attributes = /* @__PURE__ */ Object.create(null);
|
|
1087
|
+
while (this.match("lbrack")) {
|
|
1088
|
+
while (!this.match("rbrack")) {
|
|
1089
|
+
const keyToken = this.consume();
|
|
1090
|
+
if (!isIdentifierLike(keyToken)) {
|
|
1091
|
+
throw new Error("Expected attribute name.");
|
|
1092
|
+
}
|
|
1093
|
+
const key = parseIdentifierValue(keyToken);
|
|
1094
|
+
let value = true;
|
|
1095
|
+
if (this.match("equals")) {
|
|
1096
|
+
const valueToken = this.consume();
|
|
1097
|
+
value = parseAttributeValue(valueToken);
|
|
1098
|
+
}
|
|
1099
|
+
attributes[key] = value;
|
|
1100
|
+
if (((_a = this.peek()) == null ? void 0 : _a.type) === "comma" || ((_b = this.peek()) == null ? void 0 : _b.type) === "semicolon") {
|
|
1101
|
+
this.consume();
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
return attributes;
|
|
1106
|
+
}
|
|
1107
|
+
/** Creates an implicit node and records its subgraph memberships. */
|
|
1108
|
+
ensureNode(id, membership) {
|
|
1109
|
+
let node = this.result.nodes.get(id);
|
|
1110
|
+
if (!node) {
|
|
1111
|
+
const defaults = this.currentScope().nodeDefaults;
|
|
1112
|
+
node = { id, attributes: { ...defaults }, subgraphs: /* @__PURE__ */ new Set() };
|
|
1113
|
+
this.result.nodes.set(id, node);
|
|
1114
|
+
}
|
|
1115
|
+
membership.forEach((subgraphId) => node.subgraphs.add(subgraphId));
|
|
1116
|
+
return node;
|
|
1117
|
+
}
|
|
1118
|
+
/** Lists enclosing subgraphs. */
|
|
1119
|
+
getCurrentSubgraphChain() {
|
|
1120
|
+
const chain = [];
|
|
1121
|
+
for (const scope of this.scopes) {
|
|
1122
|
+
if (scope.id) {
|
|
1123
|
+
chain.push(scope.id);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return chain;
|
|
1127
|
+
}
|
|
1128
|
+
/** Finds the nearest enclosing named or generated subgraph. */
|
|
1129
|
+
findCurrentSubgraphId() {
|
|
1130
|
+
for (let index = this.scopes.length - 1; index >= 0; index--) {
|
|
1131
|
+
const scope = this.scopes[index];
|
|
1132
|
+
if (scope.id) {
|
|
1133
|
+
return scope.id;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return void 0;
|
|
1137
|
+
}
|
|
1138
|
+
/** Returns the active attribute scope. */
|
|
1139
|
+
currentScope() {
|
|
1140
|
+
return this.scopes[this.scopes.length - 1];
|
|
1141
|
+
}
|
|
1142
|
+
/** Consumes an optional statement terminator. */
|
|
1143
|
+
consumeOptionalSemicolon() {
|
|
1144
|
+
const next = this.peek();
|
|
1145
|
+
if ((next == null ? void 0 : next.type) === "semicolon") {
|
|
1146
|
+
this.consume();
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
/** Requires the next token to have the requested type. */
|
|
1150
|
+
expect(type) {
|
|
1151
|
+
const token = this.consume();
|
|
1152
|
+
if (!token || token.type !== type) {
|
|
1153
|
+
throw new Error(`Expected token ${type}.`);
|
|
1154
|
+
}
|
|
1155
|
+
return token;
|
|
1156
|
+
}
|
|
1157
|
+
/** Consumes the next token or reports truncated input. */
|
|
1158
|
+
consume() {
|
|
1159
|
+
const token = this.tokens[this.position];
|
|
1160
|
+
if (!token) {
|
|
1161
|
+
throw new Error("Unexpected end of DOT input.");
|
|
1162
|
+
}
|
|
1163
|
+
this.position++;
|
|
1164
|
+
return token;
|
|
1165
|
+
}
|
|
1166
|
+
/** Consumes a token when its type matches. */
|
|
1167
|
+
match(type) {
|
|
1168
|
+
const token = this.peek();
|
|
1169
|
+
if (token && token.type === type) {
|
|
1170
|
+
this.position++;
|
|
1171
|
+
return token;
|
|
1172
|
+
}
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
/** Inspects a token without consuming it. */
|
|
1176
|
+
peek(offset = 0) {
|
|
1177
|
+
return this.tokens[this.position + offset] ?? null;
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
IDENTIFIER_TERMINATORS = /* @__PURE__ */ new Set(["{", "}", "[", "]", "=", ";", ",", '"', "<", "#"]);
|
|
1181
|
+
}
|
|
1182
|
+
});
|
|
19
1183
|
|
|
20
|
-
//
|
|
1184
|
+
// src/dot-loader.ts
|
|
21
1185
|
var dot_loader_exports = {};
|
|
22
1186
|
__export(dot_loader_exports, {
|
|
23
1187
|
DOTLoaderWithParser: () => DOTLoaderWithParser
|
|
24
1188
|
});
|
|
25
|
-
|
|
1189
|
+
var DOTLoaderWithParser;
|
|
1190
|
+
var init_dot_loader = __esm({
|
|
1191
|
+
"src/dot-loader.ts"() {
|
|
1192
|
+
"use strict";
|
|
1193
|
+
init_dot_loader_types();
|
|
1194
|
+
init_parse_dot();
|
|
1195
|
+
DOTLoaderWithParser = {
|
|
1196
|
+
...DOTLoader,
|
|
1197
|
+
parse: async (data, options) => {
|
|
1198
|
+
var _a;
|
|
1199
|
+
return parseDOT(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
1200
|
+
},
|
|
1201
|
+
parseSync: (data, options) => {
|
|
1202
|
+
var _a;
|
|
1203
|
+
return parseDOT(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
1204
|
+
},
|
|
1205
|
+
parseTextSync: (data, options) => {
|
|
1206
|
+
var _a;
|
|
1207
|
+
return parseDOT(data, ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
// dist/dot-loader.js
|
|
1214
|
+
var dot_loader_exports2 = {};
|
|
1215
|
+
__export(dot_loader_exports2, {
|
|
1216
|
+
DOTLoaderWithParser: () => DOTLoaderWithParser2
|
|
1217
|
+
});
|
|
1218
|
+
module.exports = __toCommonJS(dot_loader_exports2);
|
|
26
1219
|
|
|
27
1220
|
// dist/dot-loader-types.js
|
|
28
|
-
var
|
|
29
|
-
|
|
1221
|
+
var VERSION2 = true ? "5.0.0-alpha.10" : "latest";
|
|
1222
|
+
async function preload2() {
|
|
1223
|
+
const { DOTLoaderWithParser: DOTLoaderWithParser3 } = await Promise.resolve().then(() => (init_dot_loader(), dot_loader_exports));
|
|
1224
|
+
return DOTLoaderWithParser3;
|
|
1225
|
+
}
|
|
1226
|
+
var DOTLoader2 = {
|
|
30
1227
|
name: "DOT",
|
|
31
1228
|
id: "dot",
|
|
32
1229
|
module: "graphs",
|
|
33
|
-
version:
|
|
1230
|
+
version: VERSION2,
|
|
34
1231
|
extensions: ["dot", "gv"],
|
|
35
1232
|
mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
|
|
36
1233
|
text: true,
|
|
37
1234
|
worker: false,
|
|
38
1235
|
dataType: null,
|
|
39
1236
|
batchType: null,
|
|
40
|
-
options: {}
|
|
1237
|
+
options: { dot: { shape: "arrow-table" } },
|
|
1238
|
+
preload: preload2
|
|
41
1239
|
};
|
|
42
1240
|
|
|
43
|
-
// dist/lib/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1241
|
+
// dist/lib/build-graph-tables.js
|
|
1242
|
+
var import_apache_arrow2 = require("apache-arrow");
|
|
1243
|
+
init_src();
|
|
1244
|
+
function buildGraphTables2(nodes, edges, shape, declarations) {
|
|
1245
|
+
if (shape === "plain-graph-data") {
|
|
1246
|
+
return { shape, nodes: Array.from(nodes), edges: Array.from(edges) };
|
|
1247
|
+
}
|
|
1248
|
+
if (shape !== "arrow-table" && shape !== "object-row-table") {
|
|
1249
|
+
throw new Error(`Unsupported graph shape: ${shape}`);
|
|
1250
|
+
}
|
|
1251
|
+
const nodeTable = buildGraphTable2(nodes, false, shape, declarations == null ? void 0 : declarations.nodes);
|
|
1252
|
+
const edgeTable = buildGraphTable2(edges, true, shape, declarations == null ? void 0 : declarations.edges);
|
|
1253
|
+
return {
|
|
1254
|
+
shape: "tables",
|
|
1255
|
+
tables: [
|
|
1256
|
+
{ name: "nodes", table: nodeTable },
|
|
1257
|
+
{ name: "edges", table: edgeTable }
|
|
1258
|
+
]
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
function buildGraphTable2(records, isEdge, shape, declarations) {
|
|
1262
|
+
const columnNames = isEdge ? ["id", "sourceId", "targetId", "directed", "label", "attributes"] : ["id", "label", "attributes"];
|
|
1263
|
+
const columns = new Map(columnNames.map((name) => [name, []]));
|
|
1264
|
+
for (const record of records) {
|
|
1265
|
+
for (const name of columnNames) {
|
|
1266
|
+
const value = record[name];
|
|
1267
|
+
columns.get(name).push(name === "id" || name === "sourceId" || name === "targetId" ? String(value) : value ?? null);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (shape === "object-row-table") {
|
|
1271
|
+
return {
|
|
1272
|
+
shape,
|
|
1273
|
+
data: columns.get("id").map((_, index) => Object.fromEntries(columnNames.map((name) => [name, columns.get(name)[index]])))
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
const vectors = /* @__PURE__ */ Object.create(null);
|
|
1277
|
+
for (const [name, values] of columns) {
|
|
1278
|
+
const type = name === "attributes" ? inferAttributeType2(values, declarations) : name === "directed" ? new import_apache_arrow2.Bool() : new import_apache_arrow2.Utf8();
|
|
1279
|
+
vectors[name] = (0, import_apache_arrow2.vectorFromArray)(values.map((value) => normalizeValue2(value, type)), type);
|
|
1280
|
+
}
|
|
1281
|
+
const data = new import_apache_arrow2.Table(vectors);
|
|
1282
|
+
return { shape, schema: convertArrowToSchema(data.schema), data };
|
|
1283
|
+
}
|
|
1284
|
+
function inferAttributeType2(values, declarations) {
|
|
1285
|
+
const names = new Set(declarations == null ? void 0 : declarations.keys());
|
|
1286
|
+
for (const value of values) {
|
|
1287
|
+
if (value && typeof value === "object") {
|
|
1288
|
+
for (const name of Object.keys(value)) {
|
|
1289
|
+
names.add(name);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
return new import_apache_arrow2.Struct(Array.from(names, (name) => {
|
|
1294
|
+
const fieldValues = values.map((value) => (value == null ? void 0 : value[name]) ?? null);
|
|
1295
|
+
return new import_apache_arrow2.Field(name, inferValueType2(fieldValues, declarations == null ? void 0 : declarations.get(name)), true);
|
|
49
1296
|
}));
|
|
1297
|
+
}
|
|
1298
|
+
function inferValueType2(values, declaration) {
|
|
1299
|
+
const present = values.filter((value) => value !== null && value !== void 0);
|
|
1300
|
+
if (declaration && typeof declaration === "object") {
|
|
1301
|
+
if (!present.every((value) => Array.isArray(value)))
|
|
1302
|
+
return new import_apache_arrow2.Utf8();
|
|
1303
|
+
return new import_apache_arrow2.List(new import_apache_arrow2.Field("item", inferValueType2(present.flatMap((value) => value), declaration.list), true));
|
|
1304
|
+
}
|
|
1305
|
+
if (declaration) {
|
|
1306
|
+
const declaredTypes = {
|
|
1307
|
+
boolean: new import_apache_arrow2.Bool(),
|
|
1308
|
+
int: new import_apache_arrow2.Int32(),
|
|
1309
|
+
long: new import_apache_arrow2.Int64(),
|
|
1310
|
+
float: new import_apache_arrow2.Float32(),
|
|
1311
|
+
double: new import_apache_arrow2.Float64(),
|
|
1312
|
+
string: new import_apache_arrow2.Utf8()
|
|
1313
|
+
};
|
|
1314
|
+
const valid = present.every((value) => {
|
|
1315
|
+
switch (declaration) {
|
|
1316
|
+
case "boolean":
|
|
1317
|
+
return typeof value === "boolean";
|
|
1318
|
+
case "int":
|
|
1319
|
+
return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
|
|
1320
|
+
case "long":
|
|
1321
|
+
return typeof value === "bigint" && value >= -(2n ** 63n) && value < 2n ** 63n;
|
|
1322
|
+
case "float":
|
|
1323
|
+
case "double":
|
|
1324
|
+
return typeof value === "number";
|
|
1325
|
+
case "string":
|
|
1326
|
+
return typeof value === "string";
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
return valid ? declaredTypes[declaration] : new import_apache_arrow2.Utf8();
|
|
1330
|
+
}
|
|
1331
|
+
if (present.length && present.every((value) => typeof value === "boolean"))
|
|
1332
|
+
return new import_apache_arrow2.Bool();
|
|
1333
|
+
if (present.length && present.every((value) => typeof value === "number"))
|
|
1334
|
+
return new import_apache_arrow2.Float64();
|
|
1335
|
+
if (present.length && present.every((value) => Array.isArray(value))) {
|
|
1336
|
+
return new import_apache_arrow2.List(new import_apache_arrow2.Field("item", inferValueType2(present.flatMap((value) => value)), true));
|
|
1337
|
+
}
|
|
1338
|
+
if (present.length && present.every((value) => typeof value === "object" && !Array.isArray(value))) {
|
|
1339
|
+
return inferAttributeType2(present);
|
|
1340
|
+
}
|
|
1341
|
+
return new import_apache_arrow2.Utf8();
|
|
1342
|
+
}
|
|
1343
|
+
function normalizeValue2(value, type) {
|
|
1344
|
+
if (value === null || value === void 0)
|
|
1345
|
+
return null;
|
|
1346
|
+
if (type instanceof import_apache_arrow2.Struct) {
|
|
1347
|
+
return Object.fromEntries(type.children.map((field) => [
|
|
1348
|
+
field.name,
|
|
1349
|
+
normalizeValue2(value[field.name], field.type)
|
|
1350
|
+
]));
|
|
1351
|
+
}
|
|
1352
|
+
if (type instanceof import_apache_arrow2.List)
|
|
1353
|
+
return value.map((item) => normalizeValue2(item, type.valueType));
|
|
1354
|
+
if (type instanceof import_apache_arrow2.Utf8 && typeof value !== "string") {
|
|
1355
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
1356
|
+
}
|
|
1357
|
+
return value;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// dist/lib/parse-dot.js
|
|
1361
|
+
function parseDOT2(input, shape = "plain-graph-data") {
|
|
1362
|
+
const parsed = parseDOTDocument2(input);
|
|
50
1363
|
return {
|
|
51
|
-
|
|
52
|
-
|
|
1364
|
+
...buildGraphTables2(iterateNodes2(parsed), iterateEdges2(parsed), shape),
|
|
1365
|
+
metadata: {
|
|
1366
|
+
id: parsed.id,
|
|
1367
|
+
directed: parsed.directed,
|
|
1368
|
+
strict: parsed.strict,
|
|
1369
|
+
attributes: { ...parsed.graphAttributes },
|
|
1370
|
+
subgraphs: Array.from(parsed.subgraphs.values(), (subgraph) => ({
|
|
1371
|
+
...subgraph,
|
|
1372
|
+
attributes: { ...subgraph.attributes }
|
|
1373
|
+
}))
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
function* iterateNodes2(parsed) {
|
|
1378
|
+
for (const node of parsed.nodes.values()) {
|
|
1379
|
+
yield {
|
|
53
1380
|
id: node.id,
|
|
54
1381
|
...typeof node.attributes.label === "string" ? { label: node.attributes.label } : {},
|
|
55
1382
|
attributes: {
|
|
56
1383
|
...node.attributes,
|
|
57
|
-
...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) =>
|
|
1384
|
+
...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) => describeSubgraph2(id, parsed.subgraphs)) } : {}
|
|
58
1385
|
}
|
|
59
|
-
}
|
|
60
|
-
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function* iterateEdges2(parsed) {
|
|
1390
|
+
for (const edge of parsed.edges) {
|
|
1391
|
+
yield {
|
|
61
1392
|
id: edge.id,
|
|
62
1393
|
sourceId: edge.sourceId,
|
|
63
1394
|
targetId: edge.targetId,
|
|
@@ -65,19 +1396,12 @@ function parseDOT(input) {
|
|
|
65
1396
|
...typeof edge.attributes.label === "string" ? { label: edge.attributes.label } : {},
|
|
66
1397
|
attributes: {
|
|
67
1398
|
...edge.attributes,
|
|
68
|
-
...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) =>
|
|
1399
|
+
...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) => describeSubgraph2(id, parsed.subgraphs)) } : {}
|
|
69
1400
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
id: parsed.id,
|
|
73
|
-
directed: parsed.directed,
|
|
74
|
-
strict: parsed.strict,
|
|
75
|
-
attributes: { ...parsed.graphAttributes },
|
|
76
|
-
subgraphs
|
|
77
|
-
}
|
|
78
|
-
};
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
79
1403
|
}
|
|
80
|
-
function
|
|
1404
|
+
function describeSubgraph2(id, descriptors) {
|
|
81
1405
|
const subgraph = descriptors.get(id);
|
|
82
1406
|
return {
|
|
83
1407
|
id,
|
|
@@ -85,7 +1409,7 @@ function describeSubgraph(id, descriptors) {
|
|
|
85
1409
|
parentId: subgraph.parentId
|
|
86
1410
|
};
|
|
87
1411
|
}
|
|
88
|
-
var
|
|
1412
|
+
var DOTParser2 = class {
|
|
89
1413
|
/** Tokens for DOT parsing. */
|
|
90
1414
|
tokens;
|
|
91
1415
|
/** Position for DOT parsing. */
|
|
@@ -121,7 +1445,7 @@ var DOTParser = class {
|
|
|
121
1445
|
constructor(tokens) {
|
|
122
1446
|
this.tokens = tokens;
|
|
123
1447
|
for (let index = 0; index < tokens.length - 1; index++) {
|
|
124
|
-
if (
|
|
1448
|
+
if (isKeyword2(tokens[index], "subgraph") && isIdentifierLike2(tokens[index + 1])) {
|
|
125
1449
|
this.namedSubgraphIds.add(tokens[index + 1].value);
|
|
126
1450
|
}
|
|
127
1451
|
}
|
|
@@ -138,19 +1462,19 @@ var DOTParser = class {
|
|
|
138
1462
|
/** Reads graph identity, declaration, and statements. */
|
|
139
1463
|
parseGraph() {
|
|
140
1464
|
const strictToken = this.peek();
|
|
141
|
-
if (strictToken &&
|
|
1465
|
+
if (strictToken && isKeyword2(strictToken, "strict")) {
|
|
142
1466
|
this.consume();
|
|
143
1467
|
this.result.strict = true;
|
|
144
1468
|
}
|
|
145
1469
|
const typeToken = this.peek();
|
|
146
|
-
if (!typeToken || !
|
|
1470
|
+
if (!typeToken || !isGraphType2(typeToken)) {
|
|
147
1471
|
throw new Error("DOT graph must start with graph or digraph keyword.");
|
|
148
1472
|
}
|
|
149
1473
|
this.consume();
|
|
150
|
-
this.result.directed =
|
|
1474
|
+
this.result.directed = isKeyword2(typeToken, "digraph");
|
|
151
1475
|
const idToken = this.peek();
|
|
152
|
-
if (idToken &&
|
|
153
|
-
this.result.id =
|
|
1476
|
+
if (idToken && isIdentifierLike2(idToken)) {
|
|
1477
|
+
this.result.id = parseIdentifierValue2(this.consume());
|
|
154
1478
|
}
|
|
155
1479
|
this.expect("lbrace");
|
|
156
1480
|
while (!this.match("rbrace")) {
|
|
@@ -178,7 +1502,7 @@ var DOTParser = class {
|
|
|
178
1502
|
if (this.tryParseAssignmentStatement(token)) {
|
|
179
1503
|
return true;
|
|
180
1504
|
}
|
|
181
|
-
if (
|
|
1505
|
+
if (isIdentifierLike2(token)) {
|
|
182
1506
|
this.parseNodeOrEdgeStatement();
|
|
183
1507
|
this.consumeOptionalSemicolon();
|
|
184
1508
|
return true;
|
|
@@ -196,7 +1520,7 @@ var DOTParser = class {
|
|
|
196
1520
|
}
|
|
197
1521
|
/** Reads a standalone subgraph statement. */
|
|
198
1522
|
tryParseSubgraphStatement(token) {
|
|
199
|
-
if (token.type !== "lbrace" && !
|
|
1523
|
+
if (token.type !== "lbrace" && !isKeyword2(token, "subgraph")) {
|
|
200
1524
|
return false;
|
|
201
1525
|
}
|
|
202
1526
|
this.parseSubgraph();
|
|
@@ -204,14 +1528,14 @@ var DOTParser = class {
|
|
|
204
1528
|
}
|
|
205
1529
|
/** Applies graph, node, or edge defaults. */
|
|
206
1530
|
tryParseKeywordStatement(token) {
|
|
207
|
-
if (!(
|
|
1531
|
+
if (!(isKeyword2(token, "graph") || isKeyword2(token, "node") || isKeyword2(token, "edge"))) {
|
|
208
1532
|
return false;
|
|
209
1533
|
}
|
|
210
1534
|
this.consume();
|
|
211
1535
|
const explicitAttributes = this.parseAttributeList();
|
|
212
|
-
if (
|
|
1536
|
+
if (isKeyword2(token, "graph")) {
|
|
213
1537
|
Object.assign(this.currentScope().graphAttributes, explicitAttributes);
|
|
214
|
-
} else if (
|
|
1538
|
+
} else if (isKeyword2(token, "node")) {
|
|
215
1539
|
Object.assign(this.currentScope().nodeDefaults, explicitAttributes);
|
|
216
1540
|
} else {
|
|
217
1541
|
Object.assign(this.currentScope().edgeDefaults, explicitAttributes);
|
|
@@ -221,34 +1545,34 @@ var DOTParser = class {
|
|
|
221
1545
|
}
|
|
222
1546
|
/** Reads a graph attribute assignment. */
|
|
223
1547
|
tryParseAssignmentStatement(token) {
|
|
224
|
-
if (!
|
|
1548
|
+
if (!isIdentifierLike2(token)) {
|
|
225
1549
|
return false;
|
|
226
1550
|
}
|
|
227
1551
|
const next = this.peek(1);
|
|
228
1552
|
if ((next == null ? void 0 : next.type) !== "equals") {
|
|
229
1553
|
return false;
|
|
230
1554
|
}
|
|
231
|
-
const key =
|
|
1555
|
+
const key = parseIdentifierValue2(this.consume());
|
|
232
1556
|
this.consume();
|
|
233
1557
|
const valueToken = this.consume();
|
|
234
|
-
const value =
|
|
1558
|
+
const value = parseAttributeValue2(valueToken);
|
|
235
1559
|
this.currentScope().graphAttributes[key] = value;
|
|
236
1560
|
this.consumeOptionalSemicolon();
|
|
237
1561
|
return true;
|
|
238
1562
|
}
|
|
239
1563
|
/** Reads a node statement or chained edges. */
|
|
240
1564
|
parseNodeOrEdgeStatement() {
|
|
241
|
-
const first =
|
|
1565
|
+
const first = parseIdentifierValue2(this.consume());
|
|
242
1566
|
const references = [first];
|
|
243
1567
|
const operators = [];
|
|
244
1568
|
let operatorToken = this.match("arrow");
|
|
245
1569
|
while (operatorToken) {
|
|
246
1570
|
operators.push(operatorToken.value);
|
|
247
1571
|
const referenceToken = this.consume();
|
|
248
|
-
if (!
|
|
1572
|
+
if (!isIdentifierLike2(referenceToken)) {
|
|
249
1573
|
throw new Error("Expected node identifier in edge statement.");
|
|
250
1574
|
}
|
|
251
|
-
references.push(
|
|
1575
|
+
references.push(parseIdentifierValue2(referenceToken));
|
|
252
1576
|
operatorToken = this.match("arrow");
|
|
253
1577
|
}
|
|
254
1578
|
if (operators.length === 0) {
|
|
@@ -278,7 +1602,7 @@ var DOTParser = class {
|
|
|
278
1602
|
if (directed !== this.result.directed) {
|
|
279
1603
|
throw new Error("DOT edge operator must match graph or digraph declaration.");
|
|
280
1604
|
}
|
|
281
|
-
const edgeId =
|
|
1605
|
+
const edgeId = deriveEdgeId2(attributes, sourceId, targetId, ++this.edgeCounter);
|
|
282
1606
|
const edgeAttributes = { ...attributes };
|
|
283
1607
|
this.ensureNode(sourceId, membership);
|
|
284
1608
|
this.ensureNode(targetId, membership);
|
|
@@ -286,11 +1610,15 @@ var DOTParser = class {
|
|
|
286
1610
|
const existingEdge = this.result.strict ? this.strictEdges.get(strictKey) : void 0;
|
|
287
1611
|
if (existingEdge) {
|
|
288
1612
|
existingEdge.attributes = { ...existingEdge.attributes, ...explicitAttributes };
|
|
289
|
-
|
|
1613
|
+
const explicitId = explicitAttributes.id ?? explicitAttributes.Id ?? explicitAttributes.ID;
|
|
1614
|
+
if (typeof explicitId === "string" || typeof explicitId === "number") {
|
|
1615
|
+
existingEdge.id = String(explicitId);
|
|
1616
|
+
}
|
|
1617
|
+
existingEdge.directed = deriveDirectedFlag2(existingEdge.attributes, directed);
|
|
290
1618
|
existingEdge.subgraphs = Array.from(/* @__PURE__ */ new Set([...existingEdge.subgraphs, ...membership]));
|
|
291
1619
|
continue;
|
|
292
1620
|
}
|
|
293
|
-
const directedOverride =
|
|
1621
|
+
const directedOverride = deriveDirectedFlag2(edgeAttributes, directed);
|
|
294
1622
|
const edge = {
|
|
295
1623
|
id: edgeId,
|
|
296
1624
|
sourceId,
|
|
@@ -309,12 +1637,12 @@ var DOTParser = class {
|
|
|
309
1637
|
parseSubgraph() {
|
|
310
1638
|
let idToken = this.peek();
|
|
311
1639
|
let subgraphId;
|
|
312
|
-
if (idToken &&
|
|
1640
|
+
if (idToken && isKeyword2(idToken, "subgraph")) {
|
|
313
1641
|
this.consume();
|
|
314
1642
|
idToken = this.peek();
|
|
315
1643
|
}
|
|
316
|
-
if (idToken &&
|
|
317
|
-
subgraphId =
|
|
1644
|
+
if (idToken && isIdentifierLike2(idToken)) {
|
|
1645
|
+
subgraphId = parseIdentifierValue2(this.consume());
|
|
318
1646
|
} else {
|
|
319
1647
|
do {
|
|
320
1648
|
subgraphId = `subgraph_${++this.subgraphCounter}`;
|
|
@@ -357,14 +1685,14 @@ var DOTParser = class {
|
|
|
357
1685
|
while (this.match("lbrack")) {
|
|
358
1686
|
while (!this.match("rbrack")) {
|
|
359
1687
|
const keyToken = this.consume();
|
|
360
|
-
if (!
|
|
1688
|
+
if (!isIdentifierLike2(keyToken)) {
|
|
361
1689
|
throw new Error("Expected attribute name.");
|
|
362
1690
|
}
|
|
363
|
-
const key =
|
|
1691
|
+
const key = parseIdentifierValue2(keyToken);
|
|
364
1692
|
let value = true;
|
|
365
1693
|
if (this.match("equals")) {
|
|
366
1694
|
const valueToken = this.consume();
|
|
367
|
-
value =
|
|
1695
|
+
value = parseAttributeValue2(valueToken);
|
|
368
1696
|
}
|
|
369
1697
|
attributes[key] = value;
|
|
370
1698
|
if (((_a = this.peek()) == null ? void 0 : _a.type) === "comma" || ((_b = this.peek()) == null ? void 0 : _b.type) === "semicolon") {
|
|
@@ -447,16 +1775,16 @@ var DOTParser = class {
|
|
|
447
1775
|
return this.tokens[this.position + offset] ?? null;
|
|
448
1776
|
}
|
|
449
1777
|
};
|
|
450
|
-
function
|
|
451
|
-
const parser = new
|
|
1778
|
+
function parseDOTDocument2(input) {
|
|
1779
|
+
const parser = new DOTParser2(tokenize2(input));
|
|
452
1780
|
return parser.parse();
|
|
453
1781
|
}
|
|
454
|
-
var
|
|
455
|
-
function
|
|
1782
|
+
var IDENTIFIER_TERMINATORS2 = /* @__PURE__ */ new Set(["{", "}", "[", "]", "=", ";", ",", '"', "<", "#"]);
|
|
1783
|
+
function tokenize2(input) {
|
|
456
1784
|
const tokens = [];
|
|
457
1785
|
let index = 0;
|
|
458
1786
|
while (index < input.length) {
|
|
459
|
-
const { token, nextIndex } =
|
|
1787
|
+
const { token, nextIndex } = readNextToken2(input, index);
|
|
460
1788
|
if (nextIndex <= index) {
|
|
461
1789
|
throw new Error(`Tokenizer did not advance at position ${index}.`);
|
|
462
1790
|
}
|
|
@@ -467,35 +1795,35 @@ function tokenize(input) {
|
|
|
467
1795
|
}
|
|
468
1796
|
return tokens;
|
|
469
1797
|
}
|
|
470
|
-
function
|
|
1798
|
+
function readNextToken2(input, index) {
|
|
471
1799
|
if (index >= input.length) {
|
|
472
1800
|
return { token: null, nextIndex: input.length };
|
|
473
1801
|
}
|
|
474
1802
|
const character = input[index];
|
|
475
|
-
if (
|
|
1803
|
+
if (isWhitespace2(character)) {
|
|
476
1804
|
return { token: null, nextIndex: index + 1 };
|
|
477
1805
|
}
|
|
478
|
-
const commentEnd =
|
|
1806
|
+
const commentEnd = skipComment2(input, index);
|
|
479
1807
|
if (commentEnd !== null) {
|
|
480
1808
|
return { token: null, nextIndex: commentEnd };
|
|
481
1809
|
}
|
|
482
|
-
const arrowToken =
|
|
1810
|
+
const arrowToken = readArrowToken2(input, index);
|
|
483
1811
|
if (arrowToken) {
|
|
484
1812
|
return arrowToken;
|
|
485
1813
|
}
|
|
486
|
-
const punctuation =
|
|
1814
|
+
const punctuation = readPunctuationToken2(character);
|
|
487
1815
|
if (punctuation) {
|
|
488
1816
|
return { token: punctuation, nextIndex: index + 1 };
|
|
489
1817
|
}
|
|
490
1818
|
if (character === '"') {
|
|
491
|
-
const { value, nextIndex } =
|
|
1819
|
+
const { value, nextIndex } = readQuotedString2(input, index + 1);
|
|
492
1820
|
return { token: { type: "string", value }, nextIndex };
|
|
493
1821
|
}
|
|
494
1822
|
if (character === "<") {
|
|
495
|
-
const { value, nextIndex } =
|
|
1823
|
+
const { value, nextIndex } = readHtmlString2(input, index + 1);
|
|
496
1824
|
return { token: { type: "html", value }, nextIndex };
|
|
497
1825
|
}
|
|
498
|
-
const identifier =
|
|
1826
|
+
const identifier = readIdentifier2(input, index);
|
|
499
1827
|
if (identifier.value) {
|
|
500
1828
|
return {
|
|
501
1829
|
token: { type: "identifier", value: identifier.value },
|
|
@@ -504,31 +1832,31 @@ function readNextToken(input, index) {
|
|
|
504
1832
|
}
|
|
505
1833
|
throw new Error(`Unexpected token at position ${index}.`);
|
|
506
1834
|
}
|
|
507
|
-
function
|
|
1835
|
+
function skipComment2(input, index) {
|
|
508
1836
|
const character = input[index];
|
|
509
1837
|
if (character === "/") {
|
|
510
1838
|
const next = input[index + 1];
|
|
511
1839
|
if (next === "/") {
|
|
512
|
-
return
|
|
1840
|
+
return skipLineComment2(input, index + 2);
|
|
513
1841
|
}
|
|
514
1842
|
if (next === "*") {
|
|
515
|
-
return
|
|
1843
|
+
return skipBlockComment2(input, index + 2);
|
|
516
1844
|
}
|
|
517
1845
|
return null;
|
|
518
1846
|
}
|
|
519
1847
|
if (character === "#") {
|
|
520
|
-
return
|
|
1848
|
+
return skipLineComment2(input, index + 1);
|
|
521
1849
|
}
|
|
522
1850
|
return null;
|
|
523
1851
|
}
|
|
524
|
-
function
|
|
1852
|
+
function skipLineComment2(input, startIndex) {
|
|
525
1853
|
let cursor = startIndex;
|
|
526
|
-
while (cursor < input.length && !
|
|
1854
|
+
while (cursor < input.length && !isLineBreak2(input[cursor])) {
|
|
527
1855
|
cursor++;
|
|
528
1856
|
}
|
|
529
1857
|
return cursor;
|
|
530
1858
|
}
|
|
531
|
-
function
|
|
1859
|
+
function skipBlockComment2(input, startIndex) {
|
|
532
1860
|
let cursor = startIndex;
|
|
533
1861
|
while (cursor < input.length) {
|
|
534
1862
|
if (input[cursor] === "*" && input[cursor + 1] === "/") {
|
|
@@ -538,7 +1866,7 @@ function skipBlockComment(input, startIndex) {
|
|
|
538
1866
|
}
|
|
539
1867
|
throw new Error("Unterminated block comment in DOT source.");
|
|
540
1868
|
}
|
|
541
|
-
function
|
|
1869
|
+
function readArrowToken2(input, index) {
|
|
542
1870
|
const next = input[index + 1];
|
|
543
1871
|
if (input[index] === "-" && next === "-") {
|
|
544
1872
|
return { token: { type: "arrow", value: "--" }, nextIndex: index + 2 };
|
|
@@ -548,7 +1876,7 @@ function readArrowToken(input, index) {
|
|
|
548
1876
|
}
|
|
549
1877
|
return null;
|
|
550
1878
|
}
|
|
551
|
-
function
|
|
1879
|
+
function readPunctuationToken2(character) {
|
|
552
1880
|
switch (character) {
|
|
553
1881
|
case "{":
|
|
554
1882
|
return { type: "lbrace", value: character };
|
|
@@ -568,7 +1896,7 @@ function readPunctuationToken(character) {
|
|
|
568
1896
|
return null;
|
|
569
1897
|
}
|
|
570
1898
|
}
|
|
571
|
-
function
|
|
1899
|
+
function readQuotedString2(input, startIndex) {
|
|
572
1900
|
let value = "";
|
|
573
1901
|
let index = startIndex;
|
|
574
1902
|
while (index < input.length) {
|
|
@@ -577,7 +1905,7 @@ function readQuotedString(input, startIndex) {
|
|
|
577
1905
|
return { value, nextIndex: index + 1 };
|
|
578
1906
|
}
|
|
579
1907
|
if (character === "\\") {
|
|
580
|
-
const escape =
|
|
1908
|
+
const escape = readEscapedCharacter2(input, index + 1);
|
|
581
1909
|
value += escape.value;
|
|
582
1910
|
index = escape.nextIndex;
|
|
583
1911
|
} else {
|
|
@@ -587,9 +1915,13 @@ function readQuotedString(input, startIndex) {
|
|
|
587
1915
|
}
|
|
588
1916
|
throw new Error("Unterminated string literal in DOT source.");
|
|
589
1917
|
}
|
|
590
|
-
function
|
|
1918
|
+
function readEscapedCharacter2(input, startIndex) {
|
|
591
1919
|
const next = input[startIndex];
|
|
592
1920
|
switch (next) {
|
|
1921
|
+
case "\n":
|
|
1922
|
+
return { value: "", nextIndex: startIndex + 1 };
|
|
1923
|
+
case "\r":
|
|
1924
|
+
return { value: "", nextIndex: startIndex + (input[startIndex + 1] === "\n" ? 2 : 1) };
|
|
593
1925
|
case "n":
|
|
594
1926
|
case "l":
|
|
595
1927
|
case "L":
|
|
@@ -606,11 +1938,11 @@ function readEscapedCharacter(input, startIndex) {
|
|
|
606
1938
|
if (typeof next === "undefined") {
|
|
607
1939
|
throw new Error("Unterminated escape sequence in DOT source.");
|
|
608
1940
|
}
|
|
609
|
-
return { value: next
|
|
1941
|
+
return { value: `\\${next}`, nextIndex: startIndex + 1 };
|
|
610
1942
|
}
|
|
611
1943
|
}
|
|
612
1944
|
}
|
|
613
|
-
function
|
|
1945
|
+
function readHtmlString2(input, startIndex) {
|
|
614
1946
|
let value = "<";
|
|
615
1947
|
let depth = 1;
|
|
616
1948
|
let index = startIndex;
|
|
@@ -629,10 +1961,10 @@ function readHtmlString(input, startIndex) {
|
|
|
629
1961
|
}
|
|
630
1962
|
throw new Error("Unterminated HTML-like string literal in DOT source.");
|
|
631
1963
|
}
|
|
632
|
-
function
|
|
1964
|
+
function readIdentifier2(input, startIndex) {
|
|
633
1965
|
let index = startIndex;
|
|
634
1966
|
let value = "";
|
|
635
|
-
while (index < input.length && !
|
|
1967
|
+
while (index < input.length && !isIdentifierTerminator2(input, index)) {
|
|
636
1968
|
value += input[index];
|
|
637
1969
|
index++;
|
|
638
1970
|
}
|
|
@@ -641,52 +1973,52 @@ function readIdentifier(input, startIndex) {
|
|
|
641
1973
|
}
|
|
642
1974
|
return { value, nextIndex: index };
|
|
643
1975
|
}
|
|
644
|
-
function
|
|
1976
|
+
function isIdentifierTerminator2(input, index) {
|
|
645
1977
|
const character = input[index];
|
|
646
|
-
if (
|
|
1978
|
+
if (isWhitespace2(character) || IDENTIFIER_TERMINATORS2.has(character)) {
|
|
647
1979
|
return true;
|
|
648
1980
|
}
|
|
649
|
-
if (
|
|
1981
|
+
if (isArrowOperatorStart2(input, index)) {
|
|
650
1982
|
return true;
|
|
651
1983
|
}
|
|
652
|
-
if (
|
|
1984
|
+
if (isCommentStart2(input, index)) {
|
|
653
1985
|
return true;
|
|
654
1986
|
}
|
|
655
1987
|
return false;
|
|
656
1988
|
}
|
|
657
|
-
function
|
|
1989
|
+
function isArrowOperatorStart2(input, index) {
|
|
658
1990
|
if (input[index] !== "-") {
|
|
659
1991
|
return false;
|
|
660
1992
|
}
|
|
661
1993
|
const next = input[index + 1];
|
|
662
1994
|
return next === "-" || next === ">";
|
|
663
1995
|
}
|
|
664
|
-
function
|
|
1996
|
+
function isCommentStart2(input, index) {
|
|
665
1997
|
if (input[index] !== "/") {
|
|
666
1998
|
return false;
|
|
667
1999
|
}
|
|
668
2000
|
const next = input[index + 1];
|
|
669
2001
|
return next === "/" || next === "*";
|
|
670
2002
|
}
|
|
671
|
-
function
|
|
2003
|
+
function isWhitespace2(character) {
|
|
672
2004
|
return character === " " || character === "\n" || character === "\r" || character === " " || character === "\f";
|
|
673
2005
|
}
|
|
674
|
-
function
|
|
2006
|
+
function isLineBreak2(character) {
|
|
675
2007
|
return character === "\n" || character === "\r";
|
|
676
2008
|
}
|
|
677
|
-
function
|
|
2009
|
+
function isKeyword2(token, keyword) {
|
|
678
2010
|
return token.type === "identifier" && token.value.toLowerCase() === keyword.toLowerCase();
|
|
679
2011
|
}
|
|
680
|
-
function
|
|
681
|
-
return
|
|
2012
|
+
function isGraphType2(token) {
|
|
2013
|
+
return isKeyword2(token, "graph") || isKeyword2(token, "digraph");
|
|
682
2014
|
}
|
|
683
|
-
function
|
|
2015
|
+
function isIdentifierLike2(token) {
|
|
684
2016
|
return token.type === "identifier" || token.type === "string" || token.type === "html";
|
|
685
2017
|
}
|
|
686
|
-
function
|
|
2018
|
+
function parseIdentifierValue2(token) {
|
|
687
2019
|
return token.value;
|
|
688
2020
|
}
|
|
689
|
-
function
|
|
2021
|
+
function parseAttributeValue2(token) {
|
|
690
2022
|
if (token.type === "string" || token.type === "html") {
|
|
691
2023
|
return token.value;
|
|
692
2024
|
}
|
|
@@ -699,14 +2031,14 @@ function parseAttributeValue(token) {
|
|
|
699
2031
|
}
|
|
700
2032
|
throw new Error("Invalid attribute value in DOT input.");
|
|
701
2033
|
}
|
|
702
|
-
function
|
|
2034
|
+
function deriveEdgeId2(attributes, sourceId, targetId, counter) {
|
|
703
2035
|
const candidate = attributes.id ?? attributes.Id ?? attributes.ID;
|
|
704
2036
|
if (typeof candidate === "string" || typeof candidate === "number") {
|
|
705
2037
|
return String(candidate);
|
|
706
2038
|
}
|
|
707
2039
|
return `${String(sourceId)}-${String(targetId)}-${counter}`;
|
|
708
2040
|
}
|
|
709
|
-
function
|
|
2041
|
+
function deriveDirectedFlag2(attributes, defaultDirected) {
|
|
710
2042
|
const candidate = attributes.directed;
|
|
711
2043
|
if (typeof candidate === "boolean") {
|
|
712
2044
|
return candidate;
|
|
@@ -723,10 +2055,19 @@ function deriveDirectedFlag(attributes, defaultDirected) {
|
|
|
723
2055
|
}
|
|
724
2056
|
|
|
725
2057
|
// dist/dot-loader.js
|
|
726
|
-
var
|
|
727
|
-
...
|
|
728
|
-
parse: async (data) =>
|
|
729
|
-
|
|
730
|
-
|
|
2058
|
+
var DOTLoaderWithParser2 = {
|
|
2059
|
+
...DOTLoader2,
|
|
2060
|
+
parse: async (data, options) => {
|
|
2061
|
+
var _a;
|
|
2062
|
+
return parseDOT2(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
2063
|
+
},
|
|
2064
|
+
parseSync: (data, options) => {
|
|
2065
|
+
var _a;
|
|
2066
|
+
return parseDOT2(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
2067
|
+
},
|
|
2068
|
+
parseTextSync: (data, options) => {
|
|
2069
|
+
var _a;
|
|
2070
|
+
return parseDOT2(data, ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow-table");
|
|
2071
|
+
}
|
|
731
2072
|
};
|
|
732
2073
|
//# sourceMappingURL=dot-loader.cjs.map
|