@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.
Files changed (84) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +123 -4
  3. package/THIRD-PARTY-NOTICES.md +17 -0
  4. package/dist/dot-loader-types.cjs +60 -0
  5. package/dist/dot-loader-types.cjs.map +7 -0
  6. package/dist/dot-loader-types.d.ts +27 -8
  7. package/dist/dot-loader-types.d.ts.map +1 -1
  8. package/dist/dot-loader-types.js +3 -2
  9. package/dist/dot-loader-types.js.map +1 -1
  10. package/dist/dot-loader.cjs +358 -47
  11. package/dist/dot-loader.cjs.map +3 -3
  12. package/dist/dot-loader.d.ts +11 -6
  13. package/dist/dot-loader.d.ts.map +1 -1
  14. package/dist/dot-loader.js +3 -3
  15. package/dist/dot-loader.js.map +1 -1
  16. package/dist/dot-types.d.ts +6 -1
  17. package/dist/dot-types.d.ts.map +1 -1
  18. package/dist/gexf-loader-types.cjs +60 -0
  19. package/dist/gexf-loader-types.cjs.map +7 -0
  20. package/dist/gexf-loader-types.d.ts +55 -0
  21. package/dist/gexf-loader-types.d.ts.map +1 -0
  22. package/dist/gexf-loader-types.js +27 -0
  23. package/dist/gexf-loader-types.js.map +1 -0
  24. package/dist/gexf-loader.cjs +2669 -0
  25. package/dist/gexf-loader.cjs.map +6 -0
  26. package/dist/gexf-loader.d.ts +25 -0
  27. package/dist/gexf-loader.d.ts.map +1 -0
  28. package/dist/gexf-loader.js +13 -0
  29. package/dist/gexf-loader.js.map +1 -0
  30. package/dist/gexf-types.d.ts +16 -0
  31. package/dist/gexf-types.d.ts.map +1 -0
  32. package/dist/gexf-types.js +5 -0
  33. package/dist/gexf-types.js.map +1 -0
  34. package/dist/graph-types.d.ts +29 -0
  35. package/dist/graph-types.d.ts.map +1 -1
  36. package/dist/graphml-loader-types.cjs +60 -0
  37. package/dist/graphml-loader-types.cjs.map +7 -0
  38. package/dist/graphml-loader-types.d.ts +26 -8
  39. package/dist/graphml-loader-types.d.ts.map +1 -1
  40. package/dist/graphml-loader-types.js +3 -2
  41. package/dist/graphml-loader-types.js.map +1 -1
  42. package/dist/graphml-loader.cjs +2032 -69
  43. package/dist/graphml-loader.cjs.map +3 -3
  44. package/dist/graphml-loader.d.ts +11 -6
  45. package/dist/graphml-loader.d.ts.map +1 -1
  46. package/dist/graphml-loader.js +3 -3
  47. package/dist/graphml-loader.js.map +1 -1
  48. package/dist/index.cjs +59 -1085
  49. package/dist/index.cjs.map +4 -3
  50. package/dist/index.d.ts +7 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/lib/build-graph-tables.d.ts +4 -0
  55. package/dist/lib/build-graph-tables.d.ts.map +1 -0
  56. package/dist/lib/build-graph-tables.js +141 -0
  57. package/dist/lib/build-graph-tables.js.map +1 -0
  58. package/dist/lib/parse-dot.d.ts +3 -1
  59. package/dist/lib/parse-dot.d.ts.map +1 -1
  60. package/dist/lib/parse-dot.js +38 -21
  61. package/dist/lib/parse-dot.js.map +1 -1
  62. package/dist/lib/parse-gexf.d.ts +5 -0
  63. package/dist/lib/parse-gexf.d.ts.map +1 -0
  64. package/dist/lib/parse-gexf.js +382 -0
  65. package/dist/lib/parse-gexf.js.map +1 -0
  66. package/dist/lib/parse-graphml.d.ts +2 -1
  67. package/dist/lib/parse-graphml.d.ts.map +1 -1
  68. package/dist/lib/parse-graphml.js +54 -31
  69. package/dist/lib/parse-graphml.js.map +1 -1
  70. package/package.json +18 -8
  71. package/src/dot-loader-types.ts +16 -5
  72. package/src/dot-loader.ts +7 -4
  73. package/src/dot-types.ts +7 -1
  74. package/src/gexf-loader-types.ts +42 -0
  75. package/src/gexf-loader.ts +17 -0
  76. package/src/gexf-types.ts +21 -0
  77. package/src/graph-types.ts +36 -0
  78. package/src/graphml-loader-types.ts +15 -5
  79. package/src/graphml-loader.ts +7 -4
  80. package/src/index.ts +9 -0
  81. package/src/lib/build-graph-tables.ts +206 -0
  82. package/src/lib/parse-dot.ts +44 -21
  83. package/src/lib/parse-gexf.ts +390 -0
  84. package/src/lib/parse-graphml.ts +92 -40
@@ -44,32 +44,190 @@ var init_dot_loader_types = __esm({
44
44
  mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
45
45
  text: true,
46
46
  worker: false,
47
+ supportsNativeArrow: true,
47
48
  dataType: null,
48
49
  batchType: null,
49
- options: {},
50
+ options: { dot: { shape: "arrow" } },
50
51
  preload
51
52
  };
52
53
  }
53
54
  });
54
55
 
56
+ // src/lib/build-graph-tables.ts
57
+ function buildGraphTables(nodes, edges, shape, declarations) {
58
+ if (shape === "plain-graph-data") {
59
+ return { shape, nodes: Array.from(nodes), edges: Array.from(edges) };
60
+ }
61
+ if (shape !== "arrow" && shape !== "object-row-table") {
62
+ throw new Error(`Unsupported graph shape: ${shape}`);
63
+ }
64
+ const nodeTable = buildGraphTable(nodes, false, shape, declarations == null ? void 0 : declarations.nodes);
65
+ const edgeTable = buildGraphTable(edges, true, shape, declarations == null ? void 0 : declarations.edges);
66
+ return {
67
+ shape: "tables",
68
+ tables: [
69
+ { name: "nodes", table: nodeTable },
70
+ { name: "edges", table: edgeTable }
71
+ ]
72
+ };
73
+ }
74
+ function buildGraphTable(records, isEdge, shape, declarations) {
75
+ const columnNames = isEdge ? ["id", "sourceId", "targetId", "directed", "label", "attributes"] : ["id", "label", "attributes"];
76
+ const columns = new Map(columnNames.map((name) => [name, []]));
77
+ for (const record of records) {
78
+ for (const name of columnNames) {
79
+ const value = record[name];
80
+ columns.get(name).push(
81
+ name === "id" || name === "sourceId" || name === "targetId" ? String(value) : value ?? null
82
+ );
83
+ }
84
+ }
85
+ if (shape === "object-row-table") {
86
+ return {
87
+ shape,
88
+ data: columns.get("id").map(
89
+ (_, index) => Object.fromEntries(columnNames.map((name) => [name, columns.get(name)[index]]))
90
+ )
91
+ };
92
+ }
93
+ const vectors = /* @__PURE__ */ Object.create(null);
94
+ for (const [name, values] of columns) {
95
+ const type = name === "attributes" ? inferAttributeType(values, declarations) : name === "directed" ? new import_apache_arrow.Bool() : new import_apache_arrow.Utf8();
96
+ vectors[name] = (0, import_apache_arrow.vectorFromArray)(
97
+ values.map((value) => normalizeValue(value, type)),
98
+ type
99
+ );
100
+ }
101
+ return new import_apache_arrow.Table(vectors);
102
+ }
103
+ function inferAttributeType(values, declarations) {
104
+ const names = new Set(declarations == null ? void 0 : declarations.keys());
105
+ for (const value of values) {
106
+ if (value && typeof value === "object") {
107
+ for (const name of Object.keys(value)) {
108
+ names.add(name);
109
+ }
110
+ }
111
+ }
112
+ return new import_apache_arrow.Struct(
113
+ Array.from(names, (name) => {
114
+ const fieldValues = values.map(
115
+ (value) => (value == null ? void 0 : value[name]) ?? null
116
+ );
117
+ return new import_apache_arrow.Field(name, inferValueType(fieldValues, declarations == null ? void 0 : declarations.get(name)), true);
118
+ })
119
+ );
120
+ }
121
+ function inferValueType(values, declaration) {
122
+ const present = values.filter((value) => value !== null && value !== void 0);
123
+ if (declaration && typeof declaration === "object") {
124
+ if (!present.every((value) => Array.isArray(value))) return new import_apache_arrow.Utf8();
125
+ return new import_apache_arrow.List(
126
+ new import_apache_arrow.Field(
127
+ "item",
128
+ inferValueType(
129
+ present.flatMap((value) => value),
130
+ declaration.list
131
+ ),
132
+ true
133
+ )
134
+ );
135
+ }
136
+ if (declaration) {
137
+ const declaredTypes = {
138
+ boolean: new import_apache_arrow.Bool(),
139
+ int: new import_apache_arrow.Int32(),
140
+ long: new import_apache_arrow.Int64(),
141
+ float: new import_apache_arrow.Float32(),
142
+ double: new import_apache_arrow.Float64(),
143
+ string: new import_apache_arrow.Utf8()
144
+ };
145
+ const valid = present.every((value) => {
146
+ switch (declaration) {
147
+ case "boolean":
148
+ return typeof value === "boolean";
149
+ case "int":
150
+ return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
151
+ case "long":
152
+ return typeof value === "bigint" && value >= -(2n ** 63n) && value < 2n ** 63n;
153
+ case "float":
154
+ case "double":
155
+ return typeof value === "number";
156
+ case "string":
157
+ return typeof value === "string";
158
+ }
159
+ });
160
+ return valid ? declaredTypes[declaration] : new import_apache_arrow.Utf8();
161
+ }
162
+ if (present.length && present.every((value) => typeof value === "boolean")) return new import_apache_arrow.Bool();
163
+ if (present.length && present.every((value) => typeof value === "number")) return new import_apache_arrow.Float64();
164
+ if (present.length && present.every((value) => Array.isArray(value))) {
165
+ return new import_apache_arrow.List(
166
+ new import_apache_arrow.Field("item", inferValueType(present.flatMap((value) => value)), true)
167
+ );
168
+ }
169
+ if (present.length && present.every((value) => typeof value === "object" && !Array.isArray(value))) {
170
+ return inferAttributeType(present);
171
+ }
172
+ return new import_apache_arrow.Utf8();
173
+ }
174
+ function normalizeValue(value, type) {
175
+ if (value === null || value === void 0) return null;
176
+ if (type instanceof import_apache_arrow.Struct) {
177
+ return Object.fromEntries(
178
+ type.children.map((field) => [
179
+ field.name,
180
+ normalizeValue(value[field.name], field.type)
181
+ ])
182
+ );
183
+ }
184
+ if (type instanceof import_apache_arrow.List)
185
+ return value.map((item) => normalizeValue(item, type.valueType));
186
+ if (type instanceof import_apache_arrow.Utf8 && typeof value !== "string") {
187
+ return typeof value === "object" ? JSON.stringify(value) : String(value);
188
+ }
189
+ return value;
190
+ }
191
+ var import_apache_arrow;
192
+ var init_build_graph_tables = __esm({
193
+ "src/lib/build-graph-tables.ts"() {
194
+ "use strict";
195
+ import_apache_arrow = require("apache-arrow");
196
+ }
197
+ });
198
+
55
199
  // src/lib/parse-dot.ts
56
- function parseDOT(input) {
200
+ function parseDOT(input, shape = "plain-graph-data") {
57
201
  const parsed = parseDOTDocument(input);
58
- const subgraphs = Array.from(parsed.subgraphs.values(), (subgraph) => ({
59
- ...subgraph,
60
- attributes: { ...subgraph.attributes }
61
- }));
62
202
  return {
63
- shape: "plain-graph-data",
64
- nodes: Array.from(parsed.nodes.values(), (node) => ({
203
+ ...buildGraphTables(iterateNodes(parsed), iterateEdges(parsed), shape),
204
+ metadata: {
205
+ id: parsed.id,
206
+ directed: parsed.directed,
207
+ strict: parsed.strict,
208
+ attributes: { ...parsed.graphAttributes },
209
+ subgraphs: Array.from(parsed.subgraphs.values(), (subgraph) => ({
210
+ ...subgraph,
211
+ attributes: { ...subgraph.attributes }
212
+ }))
213
+ }
214
+ };
215
+ }
216
+ function* iterateNodes(parsed) {
217
+ for (const node of parsed.nodes.values()) {
218
+ yield {
65
219
  id: node.id,
66
220
  ...typeof node.attributes.label === "string" ? { label: node.attributes.label } : {},
67
221
  attributes: {
68
222
  ...node.attributes,
69
223
  ...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) => describeSubgraph(id, parsed.subgraphs)) } : {}
70
224
  }
71
- })),
72
- edges: parsed.edges.map((edge) => ({
225
+ };
226
+ }
227
+ }
228
+ function* iterateEdges(parsed) {
229
+ for (const edge of parsed.edges) {
230
+ yield {
73
231
  id: edge.id,
74
232
  sourceId: edge.sourceId,
75
233
  targetId: edge.targetId,
@@ -79,15 +237,8 @@ function parseDOT(input) {
79
237
  ...edge.attributes,
80
238
  ...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) => describeSubgraph(id, parsed.subgraphs)) } : {}
81
239
  }
82
- })),
83
- metadata: {
84
- id: parsed.id,
85
- directed: parsed.directed,
86
- strict: parsed.strict,
87
- attributes: { ...parsed.graphAttributes },
88
- subgraphs
89
- }
90
- };
240
+ };
241
+ }
91
242
  }
92
243
  function describeSubgraph(id, descriptors) {
93
244
  const subgraph = descriptors.get(id);
@@ -239,6 +390,10 @@ function readQuotedString(input, startIndex) {
239
390
  function readEscapedCharacter(input, startIndex) {
240
391
  const next = input[startIndex];
241
392
  switch (next) {
393
+ case "\n":
394
+ return { value: "", nextIndex: startIndex + 1 };
395
+ case "\r":
396
+ return { value: "", nextIndex: startIndex + (input[startIndex + 1] === "\n" ? 2 : 1) };
242
397
  case "n":
243
398
  case "l":
244
399
  case "L":
@@ -255,7 +410,7 @@ function readEscapedCharacter(input, startIndex) {
255
410
  if (typeof next === "undefined") {
256
411
  throw new Error("Unterminated escape sequence in DOT source.");
257
412
  }
258
- return { value: next, nextIndex: startIndex + 1 };
413
+ return { value: `\\${next}`, nextIndex: startIndex + 1 };
259
414
  }
260
415
  }
261
416
  }
@@ -374,6 +529,7 @@ var DOTParser, IDENTIFIER_TERMINATORS;
374
529
  var init_parse_dot = __esm({
375
530
  "src/lib/parse-dot.ts"() {
376
531
  "use strict";
532
+ init_build_graph_tables();
377
533
  DOTParser = class {
378
534
  /** Tokens for DOT parsing. */
379
535
  tokens;
@@ -577,6 +733,10 @@ var init_parse_dot = __esm({
577
733
  const existingEdge = this.result.strict ? this.strictEdges.get(strictKey) : void 0;
578
734
  if (existingEdge) {
579
735
  existingEdge.attributes = { ...existingEdge.attributes, ...explicitAttributes };
736
+ const explicitId = explicitAttributes.id ?? explicitAttributes.Id ?? explicitAttributes.ID;
737
+ if (typeof explicitId === "string" || typeof explicitId === "number") {
738
+ existingEdge.id = String(explicitId);
739
+ }
580
740
  existingEdge.directed = deriveDirectedFlag(existingEdge.attributes, directed);
581
741
  existingEdge.subgraphs = Array.from(/* @__PURE__ */ new Set([...existingEdge.subgraphs, ...membership]));
582
742
  continue;
@@ -755,9 +915,18 @@ var init_dot_loader = __esm({
755
915
  init_parse_dot();
756
916
  DOTLoaderWithParser = {
757
917
  ...DOTLoader,
758
- parse: async (data) => parseDOT(new TextDecoder().decode(data)),
759
- parseSync: (data) => parseDOT(new TextDecoder().decode(data)),
760
- parseTextSync: parseDOT
918
+ parse: async (data, options) => {
919
+ var _a;
920
+ return parseDOT(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
921
+ },
922
+ parseSync: (data, options) => {
923
+ var _a;
924
+ return parseDOT(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
925
+ },
926
+ parseTextSync: (data, options) => {
927
+ var _a;
928
+ return parseDOT(data, ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
929
+ }
761
930
  };
762
931
  }
763
932
  });
@@ -770,7 +939,7 @@ __export(dot_loader_exports2, {
770
939
  module.exports = __toCommonJS(dot_loader_exports2);
771
940
 
772
941
  // dist/dot-loader-types.js
773
- var VERSION2 = true ? "5.0.0-alpha.9" : "latest";
942
+ var VERSION2 = true ? "5.0.0-beta.10" : "latest";
774
943
  async function preload2() {
775
944
  const { DOTLoaderWithParser: DOTLoaderWithParser3 } = await Promise.resolve().then(() => (init_dot_loader(), dot_loader_exports));
776
945
  return DOTLoaderWithParser3;
@@ -784,30 +953,162 @@ var DOTLoader2 = {
784
953
  mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"],
785
954
  text: true,
786
955
  worker: false,
956
+ supportsNativeArrow: true,
787
957
  dataType: null,
788
958
  batchType: null,
789
- options: {},
959
+ options: { dot: { shape: "arrow" } },
790
960
  preload: preload2
791
961
  };
792
962
 
963
+ // dist/lib/build-graph-tables.js
964
+ var import_apache_arrow2 = require("apache-arrow");
965
+ function buildGraphTables2(nodes, edges, shape, declarations) {
966
+ if (shape === "plain-graph-data") {
967
+ return { shape, nodes: Array.from(nodes), edges: Array.from(edges) };
968
+ }
969
+ if (shape !== "arrow" && shape !== "object-row-table") {
970
+ throw new Error(`Unsupported graph shape: ${shape}`);
971
+ }
972
+ const nodeTable = buildGraphTable2(nodes, false, shape, declarations == null ? void 0 : declarations.nodes);
973
+ const edgeTable = buildGraphTable2(edges, true, shape, declarations == null ? void 0 : declarations.edges);
974
+ return {
975
+ shape: "tables",
976
+ tables: [
977
+ { name: "nodes", table: nodeTable },
978
+ { name: "edges", table: edgeTable }
979
+ ]
980
+ };
981
+ }
982
+ function buildGraphTable2(records, isEdge, shape, declarations) {
983
+ const columnNames = isEdge ? ["id", "sourceId", "targetId", "directed", "label", "attributes"] : ["id", "label", "attributes"];
984
+ const columns = new Map(columnNames.map((name) => [name, []]));
985
+ for (const record of records) {
986
+ for (const name of columnNames) {
987
+ const value = record[name];
988
+ columns.get(name).push(name === "id" || name === "sourceId" || name === "targetId" ? String(value) : value ?? null);
989
+ }
990
+ }
991
+ if (shape === "object-row-table") {
992
+ return {
993
+ shape,
994
+ data: columns.get("id").map((_, index) => Object.fromEntries(columnNames.map((name) => [name, columns.get(name)[index]])))
995
+ };
996
+ }
997
+ const vectors = /* @__PURE__ */ Object.create(null);
998
+ for (const [name, values] of columns) {
999
+ const type = name === "attributes" ? inferAttributeType2(values, declarations) : name === "directed" ? new import_apache_arrow2.Bool() : new import_apache_arrow2.Utf8();
1000
+ vectors[name] = (0, import_apache_arrow2.vectorFromArray)(values.map((value) => normalizeValue2(value, type)), type);
1001
+ }
1002
+ return new import_apache_arrow2.Table(vectors);
1003
+ }
1004
+ function inferAttributeType2(values, declarations) {
1005
+ const names = new Set(declarations == null ? void 0 : declarations.keys());
1006
+ for (const value of values) {
1007
+ if (value && typeof value === "object") {
1008
+ for (const name of Object.keys(value)) {
1009
+ names.add(name);
1010
+ }
1011
+ }
1012
+ }
1013
+ return new import_apache_arrow2.Struct(Array.from(names, (name) => {
1014
+ const fieldValues = values.map((value) => (value == null ? void 0 : value[name]) ?? null);
1015
+ return new import_apache_arrow2.Field(name, inferValueType2(fieldValues, declarations == null ? void 0 : declarations.get(name)), true);
1016
+ }));
1017
+ }
1018
+ function inferValueType2(values, declaration) {
1019
+ const present = values.filter((value) => value !== null && value !== void 0);
1020
+ if (declaration && typeof declaration === "object") {
1021
+ if (!present.every((value) => Array.isArray(value)))
1022
+ return new import_apache_arrow2.Utf8();
1023
+ return new import_apache_arrow2.List(new import_apache_arrow2.Field("item", inferValueType2(present.flatMap((value) => value), declaration.list), true));
1024
+ }
1025
+ if (declaration) {
1026
+ const declaredTypes = {
1027
+ boolean: new import_apache_arrow2.Bool(),
1028
+ int: new import_apache_arrow2.Int32(),
1029
+ long: new import_apache_arrow2.Int64(),
1030
+ float: new import_apache_arrow2.Float32(),
1031
+ double: new import_apache_arrow2.Float64(),
1032
+ string: new import_apache_arrow2.Utf8()
1033
+ };
1034
+ const valid = present.every((value) => {
1035
+ switch (declaration) {
1036
+ case "boolean":
1037
+ return typeof value === "boolean";
1038
+ case "int":
1039
+ return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
1040
+ case "long":
1041
+ return typeof value === "bigint" && value >= -(2n ** 63n) && value < 2n ** 63n;
1042
+ case "float":
1043
+ case "double":
1044
+ return typeof value === "number";
1045
+ case "string":
1046
+ return typeof value === "string";
1047
+ }
1048
+ });
1049
+ return valid ? declaredTypes[declaration] : new import_apache_arrow2.Utf8();
1050
+ }
1051
+ if (present.length && present.every((value) => typeof value === "boolean"))
1052
+ return new import_apache_arrow2.Bool();
1053
+ if (present.length && present.every((value) => typeof value === "number"))
1054
+ return new import_apache_arrow2.Float64();
1055
+ if (present.length && present.every((value) => Array.isArray(value))) {
1056
+ return new import_apache_arrow2.List(new import_apache_arrow2.Field("item", inferValueType2(present.flatMap((value) => value)), true));
1057
+ }
1058
+ if (present.length && present.every((value) => typeof value === "object" && !Array.isArray(value))) {
1059
+ return inferAttributeType2(present);
1060
+ }
1061
+ return new import_apache_arrow2.Utf8();
1062
+ }
1063
+ function normalizeValue2(value, type) {
1064
+ if (value === null || value === void 0)
1065
+ return null;
1066
+ if (type instanceof import_apache_arrow2.Struct) {
1067
+ return Object.fromEntries(type.children.map((field) => [
1068
+ field.name,
1069
+ normalizeValue2(value[field.name], field.type)
1070
+ ]));
1071
+ }
1072
+ if (type instanceof import_apache_arrow2.List)
1073
+ return value.map((item) => normalizeValue2(item, type.valueType));
1074
+ if (type instanceof import_apache_arrow2.Utf8 && typeof value !== "string") {
1075
+ return typeof value === "object" ? JSON.stringify(value) : String(value);
1076
+ }
1077
+ return value;
1078
+ }
1079
+
793
1080
  // dist/lib/parse-dot.js
794
- function parseDOT2(input) {
1081
+ function parseDOT2(input, shape = "plain-graph-data") {
795
1082
  const parsed = parseDOTDocument2(input);
796
- const subgraphs = Array.from(parsed.subgraphs.values(), (subgraph) => ({
797
- ...subgraph,
798
- attributes: { ...subgraph.attributes }
799
- }));
800
1083
  return {
801
- shape: "plain-graph-data",
802
- nodes: Array.from(parsed.nodes.values(), (node) => ({
1084
+ ...buildGraphTables2(iterateNodes2(parsed), iterateEdges2(parsed), shape),
1085
+ metadata: {
1086
+ id: parsed.id,
1087
+ directed: parsed.directed,
1088
+ strict: parsed.strict,
1089
+ attributes: { ...parsed.graphAttributes },
1090
+ subgraphs: Array.from(parsed.subgraphs.values(), (subgraph) => ({
1091
+ ...subgraph,
1092
+ attributes: { ...subgraph.attributes }
1093
+ }))
1094
+ }
1095
+ };
1096
+ }
1097
+ function* iterateNodes2(parsed) {
1098
+ for (const node of parsed.nodes.values()) {
1099
+ yield {
803
1100
  id: node.id,
804
1101
  ...typeof node.attributes.label === "string" ? { label: node.attributes.label } : {},
805
1102
  attributes: {
806
1103
  ...node.attributes,
807
1104
  ...node.subgraphs.size ? { subgraphs: Array.from(node.subgraphs, (id) => describeSubgraph2(id, parsed.subgraphs)) } : {}
808
1105
  }
809
- })),
810
- edges: parsed.edges.map((edge) => ({
1106
+ };
1107
+ }
1108
+ }
1109
+ function* iterateEdges2(parsed) {
1110
+ for (const edge of parsed.edges) {
1111
+ yield {
811
1112
  id: edge.id,
812
1113
  sourceId: edge.sourceId,
813
1114
  targetId: edge.targetId,
@@ -817,15 +1118,8 @@ function parseDOT2(input) {
817
1118
  ...edge.attributes,
818
1119
  ...edge.subgraphs.length ? { subgraphs: edge.subgraphs.map((id) => describeSubgraph2(id, parsed.subgraphs)) } : {}
819
1120
  }
820
- })),
821
- metadata: {
822
- id: parsed.id,
823
- directed: parsed.directed,
824
- strict: parsed.strict,
825
- attributes: { ...parsed.graphAttributes },
826
- subgraphs
827
- }
828
- };
1121
+ };
1122
+ }
829
1123
  }
830
1124
  function describeSubgraph2(id, descriptors) {
831
1125
  const subgraph = descriptors.get(id);
@@ -1036,6 +1330,10 @@ var DOTParser2 = class {
1036
1330
  const existingEdge = this.result.strict ? this.strictEdges.get(strictKey) : void 0;
1037
1331
  if (existingEdge) {
1038
1332
  existingEdge.attributes = { ...existingEdge.attributes, ...explicitAttributes };
1333
+ const explicitId = explicitAttributes.id ?? explicitAttributes.Id ?? explicitAttributes.ID;
1334
+ if (typeof explicitId === "string" || typeof explicitId === "number") {
1335
+ existingEdge.id = String(explicitId);
1336
+ }
1039
1337
  existingEdge.directed = deriveDirectedFlag2(existingEdge.attributes, directed);
1040
1338
  existingEdge.subgraphs = Array.from(/* @__PURE__ */ new Set([...existingEdge.subgraphs, ...membership]));
1041
1339
  continue;
@@ -1340,6 +1638,10 @@ function readQuotedString2(input, startIndex) {
1340
1638
  function readEscapedCharacter2(input, startIndex) {
1341
1639
  const next = input[startIndex];
1342
1640
  switch (next) {
1641
+ case "\n":
1642
+ return { value: "", nextIndex: startIndex + 1 };
1643
+ case "\r":
1644
+ return { value: "", nextIndex: startIndex + (input[startIndex + 1] === "\n" ? 2 : 1) };
1343
1645
  case "n":
1344
1646
  case "l":
1345
1647
  case "L":
@@ -1356,7 +1658,7 @@ function readEscapedCharacter2(input, startIndex) {
1356
1658
  if (typeof next === "undefined") {
1357
1659
  throw new Error("Unterminated escape sequence in DOT source.");
1358
1660
  }
1359
- return { value: next, nextIndex: startIndex + 1 };
1661
+ return { value: `\\${next}`, nextIndex: startIndex + 1 };
1360
1662
  }
1361
1663
  }
1362
1664
  }
@@ -1475,8 +1777,17 @@ function deriveDirectedFlag2(attributes, defaultDirected) {
1475
1777
  // dist/dot-loader.js
1476
1778
  var DOTLoaderWithParser2 = {
1477
1779
  ...DOTLoader2,
1478
- parse: async (data) => parseDOT2(new TextDecoder().decode(data)),
1479
- parseSync: (data) => parseDOT2(new TextDecoder().decode(data)),
1480
- parseTextSync: parseDOT2
1780
+ parse: async (data, options) => {
1781
+ var _a;
1782
+ return parseDOT2(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
1783
+ },
1784
+ parseSync: (data, options) => {
1785
+ var _a;
1786
+ return parseDOT2(new TextDecoder().decode(data), ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
1787
+ },
1788
+ parseTextSync: (data, options) => {
1789
+ var _a;
1790
+ return parseDOT2(data, ((_a = options == null ? void 0 : options.dot) == null ? void 0 : _a.shape) ?? "arrow");
1791
+ }
1481
1792
  };
1482
1793
  //# sourceMappingURL=dot-loader.cjs.map