@graphty/graph-io 0.3.40 → 0.3.42

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 (210) hide show
  1. package/README.md +2 -0
  2. package/dist/chunks/{children-CL3Cy0ez.js → children-CA4coBi0.js} +36 -27
  3. package/dist/chunks/children-CA4coBi0.js.map +1 -0
  4. package/dist/chunks/{choose-CS3fvGT1.js → choose-DvpbdRuz.js} +2 -2
  5. package/dist/chunks/{choose-CS3fvGT1.js.map → choose-DvpbdRuz.js.map} +1 -1
  6. package/dist/chunks/{constants-DqKZT6cH.js → constants-fT3E8JYY.js} +2 -2
  7. package/dist/chunks/{constants-DqKZT6cH.js.map → constants-fT3E8JYY.js.map} +1 -1
  8. package/dist/chunks/{escape-BJRLd3vJ.js → escape-B62ZGM_a.js} +2 -2
  9. package/dist/chunks/{escape-BJRLd3vJ.js.map → escape-B62ZGM_a.js.map} +1 -1
  10. package/dist/chunks/{export-B-aVCwyG.js → export-rKLeGQMo.js} +404 -243
  11. package/dist/chunks/export-rKLeGQMo.js.map +1 -0
  12. package/dist/chunks/{exporter-6ocL_9x_.js → exporter-8hLNemFk.js} +4 -4
  13. package/dist/chunks/{exporter-6ocL_9x_.js.map → exporter-8hLNemFk.js.map} +1 -1
  14. package/dist/chunks/{exporter-BVXnV9-9.js → exporter-BWwEuOPT.js} +29 -17
  15. package/dist/chunks/exporter-BWwEuOPT.js.map +1 -0
  16. package/dist/chunks/{exporter-Bcp-l4Bo.js → exporter-CpRyHZ3H.js} +574 -475
  17. package/dist/chunks/exporter-CpRyHZ3H.js.map +1 -0
  18. package/dist/chunks/{exporter-SFYkDzD0.js → exporter-yLxKBvLE.js} +23 -20
  19. package/dist/chunks/{exporter-SFYkDzD0.js.map → exporter-yLxKBvLE.js.map} +1 -1
  20. package/dist/chunks/{importer-DcKB97kW.js → importer-BbNb7eNg.js} +111 -71
  21. package/dist/chunks/importer-BbNb7eNg.js.map +1 -0
  22. package/dist/chunks/{importer-D_srHyj6.js → importer-C98dpSH4.js} +5 -5
  23. package/dist/chunks/{importer-D_srHyj6.js.map → importer-C98dpSH4.js.map} +1 -1
  24. package/dist/chunks/{importer-BJlGAOht.js → importer-D794XUTe.js} +3 -3
  25. package/dist/chunks/{importer-BJlGAOht.js.map → importer-D794XUTe.js.map} +1 -1
  26. package/dist/chunks/{importer-AjwOJrn2.js → importer-Dz7tI8Sa.js} +202 -181
  27. package/dist/chunks/importer-Dz7tI8Sa.js.map +1 -0
  28. package/dist/chunks/{importer-DEp_fYjf.js → importer-Ht7LNg8L.js} +92 -64
  29. package/dist/chunks/importer-Ht7LNg8L.js.map +1 -0
  30. package/dist/chunks/{importer-CPqnIY8m.js → importer-WrGRZb0N.js} +42 -29
  31. package/dist/chunks/importer-WrGRZb0N.js.map +1 -0
  32. package/dist/chunks/{importer-BpuS3J8C.js → importer-xZ-3suY1.js} +74 -61
  33. package/dist/chunks/importer-xZ-3suY1.js.map +1 -0
  34. package/dist/chunks/{json-elements-DpO6AXIc.js → json-elements-DKSqpNW1.js} +3 -3
  35. package/dist/chunks/{json-elements-DpO6AXIc.js.map → json-elements-DKSqpNW1.js.map} +1 -1
  36. package/dist/chunks/{ontology-export-50L9DOV4.js → ontology-export-CtRXjg_i.js} +2 -2
  37. package/dist/chunks/{ontology-export-50L9DOV4.js.map → ontology-export-CtRXjg_i.js.map} +1 -1
  38. package/dist/chunks/{records-r3SFHz11.js → records-Cu4bxYOm.js} +69 -36
  39. package/dist/chunks/records-Cu4bxYOm.js.map +1 -0
  40. package/dist/chunks/{text-Bjfa1xYL.js → text-DHOJXnED.js} +20 -11
  41. package/dist/chunks/text-DHOJXnED.js.map +1 -0
  42. package/dist/csv.js +323 -241
  43. package/dist/csv.js.map +1 -1
  44. package/dist/cx.js +1 -1
  45. package/dist/cx2.js +2 -2
  46. package/dist/cys.js +1 -1
  47. package/dist/dot.js +1 -1
  48. package/dist/gexf.js +195 -97
  49. package/dist/gexf.js.map +1 -1
  50. package/dist/gml.js +170 -149
  51. package/dist/gml.js.map +1 -1
  52. package/dist/graph-io.js +27 -27
  53. package/dist/graphml.js +2 -2
  54. package/dist/json.js +1 -1
  55. package/dist/neo4j.js +103 -65
  56. package/dist/neo4j.js.map +1 -1
  57. package/dist/obo.js +1 -1
  58. package/dist/pajek.js +1 -1
  59. package/dist/src/children.d.ts.map +1 -1
  60. package/dist/src/children.js +50 -27
  61. package/dist/src/children.js.map +1 -1
  62. package/dist/src/common/attributes.d.ts.map +1 -1
  63. package/dist/src/common/attributes.js +86 -42
  64. package/dist/src/common/attributes.js.map +1 -1
  65. package/dist/src/common/input.d.ts.map +1 -1
  66. package/dist/src/common/input.js +358 -184
  67. package/dist/src/common/input.js.map +1 -1
  68. package/dist/src/common/lists.js +30 -15
  69. package/dist/src/common/lists.js.map +1 -1
  70. package/dist/src/common/text.d.ts +7 -0
  71. package/dist/src/common/text.d.ts.map +1 -1
  72. package/dist/src/common/text.js +15 -7
  73. package/dist/src/common/text.js.map +1 -1
  74. package/dist/src/common/zip.d.ts.map +1 -1
  75. package/dist/src/common/zip.js +36 -19
  76. package/dist/src/common/zip.js.map +1 -1
  77. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  78. package/dist/src/formats/csv/exporter.js +288 -146
  79. package/dist/src/formats/csv/exporter.js.map +1 -1
  80. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  81. package/dist/src/formats/csv/importer.js +129 -80
  82. package/dist/src/formats/csv/importer.js.map +1 -1
  83. package/dist/src/formats/csv/records.d.ts.map +1 -1
  84. package/dist/src/formats/csv/records.js +78 -36
  85. package/dist/src/formats/csv/records.js.map +1 -1
  86. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  87. package/dist/src/formats/cys/tables.js +11 -8
  88. package/dist/src/formats/cys/tables.js.map +1 -1
  89. package/dist/src/formats/dot/tokenizer.d.ts +39 -0
  90. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
  91. package/dist/src/formats/dot/tokenizer.js +112 -66
  92. package/dist/src/formats/dot/tokenizer.js.map +1 -1
  93. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  94. package/dist/src/formats/gexf/exporter.js +65 -37
  95. package/dist/src/formats/gexf/exporter.js.map +1 -1
  96. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  97. package/dist/src/formats/gexf/importer.js +138 -50
  98. package/dist/src/formats/gexf/importer.js.map +1 -1
  99. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  100. package/dist/src/formats/gml/exporter.js +51 -35
  101. package/dist/src/formats/gml/exporter.js.map +1 -1
  102. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  103. package/dist/src/formats/gml/importer.js +103 -58
  104. package/dist/src/formats/gml/importer.js.map +1 -1
  105. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  106. package/dist/src/formats/gml/syntax.js +17 -8
  107. package/dist/src/formats/gml/syntax.js.map +1 -1
  108. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  109. package/dist/src/formats/graphml/exporter.js +34 -24
  110. package/dist/src/formats/graphml/exporter.js.map +1 -1
  111. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  112. package/dist/src/formats/graphml/importer.js +17 -13
  113. package/dist/src/formats/graphml/importer.js.map +1 -1
  114. package/dist/src/formats/graphml/tree.js +23 -14
  115. package/dist/src/formats/graphml/tree.js.map +1 -1
  116. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  117. package/dist/src/formats/graphml/yfiles.js +22 -10
  118. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  119. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  120. package/dist/src/formats/json/dialect.js +54 -20
  121. package/dist/src/formats/json/dialect.js.map +1 -1
  122. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  123. package/dist/src/formats/json/exporter.js +38 -21
  124. package/dist/src/formats/json/exporter.js.map +1 -1
  125. package/dist/src/formats/json/importer.d.ts.map +1 -1
  126. package/dist/src/formats/json/importer.js +536 -343
  127. package/dist/src/formats/json/importer.js.map +1 -1
  128. package/dist/src/formats/json/obographs.js +29 -17
  129. package/dist/src/formats/json/obographs.js.map +1 -1
  130. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  131. package/dist/src/formats/neo4j/exporter.js +73 -43
  132. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  133. package/dist/src/formats/neo4j/header.d.ts.map +1 -1
  134. package/dist/src/formats/neo4j/header.js +37 -16
  135. package/dist/src/formats/neo4j/header.js.map +1 -1
  136. package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
  137. package/dist/src/formats/neo4j/importer.js +21 -11
  138. package/dist/src/formats/neo4j/importer.js.map +1 -1
  139. package/dist/src/formats/obo/exporter.d.ts.map +1 -1
  140. package/dist/src/formats/obo/exporter.js +18 -7
  141. package/dist/src/formats/obo/exporter.js.map +1 -1
  142. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  143. package/dist/src/formats/pajek/exporter.js +142 -73
  144. package/dist/src/formats/pajek/exporter.js.map +1 -1
  145. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  146. package/dist/src/formats/pajek/importer.js +26 -15
  147. package/dist/src/formats/pajek/importer.js.map +1 -1
  148. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  149. package/dist/src/formats/pajek/syntax.js +85 -58
  150. package/dist/src/formats/pajek/syntax.js.map +1 -1
  151. package/dist/src/formats/xgmml/emit.d.ts +7 -0
  152. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  153. package/dist/src/formats/xgmml/emit.js +79 -40
  154. package/dist/src/formats/xgmml/emit.js.map +1 -1
  155. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  156. package/dist/src/formats/xgmml/exporter.js +38 -12
  157. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  158. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  159. package/dist/src/formats/xgmml/importer.js +38 -18
  160. package/dist/src/formats/xgmml/importer.js.map +1 -1
  161. package/dist/src/sniff.js +109 -57
  162. package/dist/src/sniff.js.map +1 -1
  163. package/dist/xgmml.js +2 -2
  164. package/package.json +2 -2
  165. package/src/children.ts +54 -27
  166. package/src/common/attributes.ts +118 -49
  167. package/src/common/input.ts +439 -197
  168. package/src/common/lists.ts +29 -15
  169. package/src/common/text.ts +24 -15
  170. package/src/common/zip.ts +47 -18
  171. package/src/formats/csv/exporter.ts +377 -175
  172. package/src/formats/csv/importer.ts +155 -84
  173. package/src/formats/csv/records.ts +90 -35
  174. package/src/formats/cys/tables.ts +11 -10
  175. package/src/formats/dot/tokenizer.ts +118 -68
  176. package/src/formats/gexf/exporter.ts +67 -36
  177. package/src/formats/gexf/importer.ts +173 -63
  178. package/src/formats/gml/exporter.ts +78 -82
  179. package/src/formats/gml/importer.ts +119 -68
  180. package/src/formats/gml/syntax.ts +18 -8
  181. package/src/formats/graphml/exporter.ts +44 -24
  182. package/src/formats/graphml/importer.ts +18 -11
  183. package/src/formats/graphml/tree.ts +22 -12
  184. package/src/formats/graphml/yfiles.ts +23 -10
  185. package/src/formats/json/dialect.ts +61 -22
  186. package/src/formats/json/exporter.ts +40 -21
  187. package/src/formats/json/importer.ts +701 -385
  188. package/src/formats/json/obographs.ts +35 -15
  189. package/src/formats/neo4j/exporter.ts +79 -41
  190. package/src/formats/neo4j/header.ts +50 -16
  191. package/src/formats/neo4j/importer.ts +21 -10
  192. package/src/formats/obo/exporter.ts +34 -17
  193. package/src/formats/pajek/exporter.ts +180 -117
  194. package/src/formats/pajek/importer.ts +27 -15
  195. package/src/formats/pajek/syntax.ts +99 -58
  196. package/src/formats/xgmml/emit.ts +88 -40
  197. package/src/formats/xgmml/exporter.ts +40 -12
  198. package/src/formats/xgmml/importer.ts +45 -23
  199. package/src/sniff.ts +115 -59
  200. package/dist/chunks/children-CL3Cy0ez.js.map +0 -1
  201. package/dist/chunks/export-B-aVCwyG.js.map +0 -1
  202. package/dist/chunks/exporter-BVXnV9-9.js.map +0 -1
  203. package/dist/chunks/exporter-Bcp-l4Bo.js.map +0 -1
  204. package/dist/chunks/importer-AjwOJrn2.js.map +0 -1
  205. package/dist/chunks/importer-BpuS3J8C.js.map +0 -1
  206. package/dist/chunks/importer-CPqnIY8m.js.map +0 -1
  207. package/dist/chunks/importer-DEp_fYjf.js.map +0 -1
  208. package/dist/chunks/importer-DcKB97kW.js.map +0 -1
  209. package/dist/chunks/records-r3SFHz11.js.map +0 -1
  210. package/dist/chunks/text-Bjfa1xYL.js.map +0 -1
@@ -237,19 +237,7 @@ export function membersOf(
237
237
  const edges: EdgeRec[] = [];
238
238
  let dangling = 0;
239
239
  for (const member of graph.members) {
240
- if (member.href === null) {
241
- if (member.kind === "node") {
242
- nodes.push(member);
243
- } else {
244
- edges.push(member);
245
- }
246
- continue;
247
- }
248
- const id = localRef(member.href);
249
- let target: NodeRec | EdgeRec | undefined;
250
- if (id !== null) {
251
- target = member.kind === "node" ? nodeById.get(id) : edgeById.get(id);
252
- }
240
+ const target = resolveMember(member, nodeById, edgeById);
253
241
  if (target === undefined) {
254
242
  dangling++;
255
243
  } else if (target.kind === "node") {
@@ -261,6 +249,29 @@ export function membersOf(
261
249
  return { nodes, edges, dangling };
262
250
  }
263
251
 
252
+ /**
253
+ * The record a graph member stands for: itself when declared in place, else the node or edge its
254
+ * local `#id` reference names.
255
+ * @param member - the member
256
+ * @param nodeById - the first node declaration of each id
257
+ * @param edgeById - the first edge declaration of each id
258
+ * @returns the record, or undefined for a cross-file, malformed or dangling reference
259
+ */
260
+ function resolveMember(
261
+ member: NodeRec | EdgeRec,
262
+ nodeById: ReadonlyMap<string, NodeRec>,
263
+ edgeById: ReadonlyMap<string, EdgeRec>,
264
+ ): NodeRec | EdgeRec | undefined {
265
+ if (member.href === null) {
266
+ return member;
267
+ }
268
+ const id = localRef(member.href);
269
+ if (id === null) {
270
+ return undefined;
271
+ }
272
+ return member.kind === "node" ? nodeById.get(id) : edgeById.get(id);
273
+ }
274
+
264
275
  /**
265
276
  * The first declaration of each id.
266
277
  * @param records - node or edge records
@@ -276,6 +287,42 @@ function indexById<T extends NodeRec | EdgeRec>(records: readonly T[]): Map<stri
276
287
  return out;
277
288
  }
278
289
 
290
+ /**
291
+ * Whether an edge repeats one already seen, remembering it otherwise: a repeat has the same id,
292
+ * or without one the same label and endpoints.
293
+ * @param seen - the keys seen so far, or null when repeats are kept
294
+ * @param record - the edge
295
+ * @returns true for a repeat
296
+ */
297
+ function isRepeat(seen: Set<string> | null, record: EdgeRec): boolean {
298
+ if (seen === null) {
299
+ return false;
300
+ }
301
+ const key =
302
+ record.id ?? (record.label === null ? null : JSON.stringify([record.label, record.source, record.target]));
303
+ if (key === null) {
304
+ return false;
305
+ }
306
+ if (seen.has(key)) {
307
+ return true;
308
+ }
309
+ seen.add(key);
310
+ return false;
311
+ }
312
+
313
+ /**
314
+ * Whether a graph's att is one of its values: not RDF metadata, not the unnamed holder of a
315
+ * nested graph.
316
+ * @param att - the att
317
+ * @returns true to write it to the graph table
318
+ */
319
+ function isGraphValueAtt(att: AttRec): boolean {
320
+ if (att.name !== null && META_ATTS.has(att.name)) {
321
+ return false;
322
+ }
323
+ return !(att.hasGraph && att.name === null);
324
+ }
325
+
279
326
  /** Per-node state while emitting. */
280
327
  interface NodeRow {
281
328
  readonly id: string;
@@ -731,16 +778,7 @@ export class XgmmlEmitter {
731
778
  if (graph.owner !== null && isGroup(graph.owner)) {
732
779
  continue;
733
780
  }
734
- for (const member of graph.members) {
735
- if (member.href === null) {
736
- continue;
737
- }
738
- const id = localRef(member.href);
739
- const known = id !== null && (member.kind === "node" ? this.rows.has(id) : edgeIds.has(id));
740
- if (!known) {
741
- dangling++;
742
- }
743
- }
781
+ dangling += this.danglingReferences(graph, edgeIds);
744
782
  }
745
783
  if (dangling > 0) {
746
784
  this.report.warning(
@@ -751,6 +789,27 @@ export class XgmmlEmitter {
751
789
  }
752
790
  }
753
791
 
792
+ /**
793
+ * How many `xlink:href` members of a graph name no node or edge of the document.
794
+ * @param graph - the graph
795
+ * @param edgeIds - the id of every edge
796
+ * @returns the count
797
+ */
798
+ private danglingReferences(graph: GraphRec, edgeIds: ReadonlySet<string | null>): number {
799
+ let dangling = 0;
800
+ for (const member of graph.members) {
801
+ if (member.href === null) {
802
+ continue;
803
+ }
804
+ const id = localRef(member.href);
805
+ const known = id !== null && (member.kind === "node" ? this.rows.has(id) : edgeIds.has(id));
806
+ if (!known) {
807
+ dangling++;
808
+ }
809
+ }
810
+ return dangling;
811
+ }
812
+
754
813
  /**
755
814
  * Write the per-node values: label, attributes, XML attributes, graphics, positions, nested
756
815
  * network pointers and subgraph memberships.
@@ -966,17 +1025,10 @@ export class XgmmlEmitter {
966
1025
  this.decideNameLabel("edge", records);
967
1026
  for (const record of records) {
968
1027
  const where = { line: record.line, element: record.id ?? record.label };
969
- // a repeat has the same id, or without one the same label and endpoints
970
- const key =
971
- record.id ??
972
- (record.label === null ? null : JSON.stringify([record.label, record.source, record.target]));
973
- if (dedupe !== null && key !== null) {
974
- if (dedupe.has(key)) {
975
- repeats++;
976
- firstRepeat ??= where;
977
- continue;
978
- }
979
- dedupe.add(key);
1028
+ if (isRepeat(dedupe, record)) {
1029
+ repeats++;
1030
+ firstRepeat ??= where;
1031
+ continue;
980
1032
  }
981
1033
  const index = this.addEdge(record, header, ids, where);
982
1034
  this.checkAbort();
@@ -1244,13 +1296,9 @@ export class XgmmlEmitter {
1244
1296
  }
1245
1297
  }
1246
1298
  for (const att of g.atts) {
1247
- if (att.name !== null && META_ATTS.has(att.name)) {
1248
- continue;
1249
- }
1250
- if (att.hasGraph && att.name === null) {
1251
- continue;
1299
+ if (isGraphValueAtt(att)) {
1300
+ this.graphColumns.addAtt(0, att, where);
1252
1301
  }
1253
- this.graphColumns.addAtt(0, att, where);
1254
1302
  }
1255
1303
  this.graphColumns.write(this.sink, () => 0);
1256
1304
  const json: Record<string, unknown> = { ...this.extras.graphJson };
@@ -394,6 +394,17 @@ function slotOf(column: Column, domain: "graph" | "node" | "edge", hasLabelRole:
394
394
  if (domain !== "node") {
395
395
  return "att";
396
396
  }
397
+ return nodeSlotOf(column);
398
+ }
399
+
400
+ /**
401
+ * Where a node column goes when it is no XML attribute, label or graphics: one of the node-only
402
+ * slots, else a typed att.
403
+ * @param column - the column
404
+ * @returns the slot
405
+ */
406
+ function nodeSlotOf(column: Column): ColumnWrite["kind"] {
407
+ const { meta } = column;
397
408
  if (meta.name === Z_COLUMN && meta.dtype === "f64" && meta.role === null) {
398
409
  return "z";
399
410
  }
@@ -1004,18 +1015,7 @@ function cellOf(column: Column | null, row: number): unknown {
1004
1015
  * @returns the coordinates as XML attributes
1005
1016
  */
1006
1017
  function coordsOf(plan: Plan, zColumn: Column | null, node: number): [string, string][] {
1007
- const out: [string, string][] = [];
1008
- const xyz = cellOf(plan.position, node);
1009
- if (xyz !== null) {
1010
- const [x, y, z] = Array.from(xyz as ArrayLike<number>);
1011
- const fmt = plan.position?.dtype === "f32" ? formatF32 : formatF64;
1012
- if (Number.isFinite(x) && Number.isFinite(y)) {
1013
- out.push(["x", fmt(x)], ["y", fmt(y === 0 ? 0 : -y)]);
1014
- if (zColumn === null && z !== undefined && z !== 0 && Number.isFinite(z)) {
1015
- out.push(["z", fmt(z)]);
1016
- }
1017
- }
1018
- }
1018
+ const out = positionCoordsOf(plan, zColumn, node);
1019
1019
  const z = cellOf(zColumn, node);
1020
1020
  if (typeof z === "number") {
1021
1021
  out.push(["z", formatF64(z)]);
@@ -1023,6 +1023,34 @@ function coordsOf(plan: Plan, zColumn: Column | null, node: number): [string, st
1023
1023
  return out;
1024
1024
  }
1025
1025
 
1026
+ /**
1027
+ * The graphics coordinates a node's position gives: x, y negated back to screen coordinates, and
1028
+ * z when no z column carries it.
1029
+ * @param plan - the plan
1030
+ * @param zColumn - the z column, or null
1031
+ * @param node - the node
1032
+ * @returns the coordinates as XML attributes (none for an unset or non-finite position)
1033
+ */
1034
+ function positionCoordsOf(plan: Plan, zColumn: Column | null, node: number): [string, string][] {
1035
+ const xyz = cellOf(plan.position, node);
1036
+ if (xyz === null) {
1037
+ return [];
1038
+ }
1039
+ const [x, y, z] = Array.from(xyz as ArrayLike<number>);
1040
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
1041
+ return [];
1042
+ }
1043
+ const fmt = plan.position?.dtype === "f32" ? formatF32 : formatF64;
1044
+ const out: [string, string][] = [
1045
+ ["x", fmt(x)],
1046
+ ["y", fmt(y === 0 ? 0 : -y)],
1047
+ ];
1048
+ if (zColumn === null && z !== undefined && z !== 0 && Number.isFinite(z)) {
1049
+ out.push(["z", fmt(z)]);
1050
+ }
1051
+ return out;
1052
+ }
1053
+
1026
1054
  /**
1027
1055
  * The group marker and the nested `<graph>` of a group node: its own id, label and atts, and an
1028
1056
  * `xlink:href` to each child.
@@ -174,23 +174,7 @@ export async function parseXgmml(
174
174
  common: ResolvedImportOptions,
175
175
  options: XgmmlImportOptions | undefined,
176
176
  ): Promise<XgmmlDocument> {
177
- const repairs: XmlRepairs = {
178
- bareAmpersand: booleanOption("repairBareAmpersands", options?.repairBareAmpersands, false)
179
- ? (line): void => {
180
- report.warning("parse-error", XGMML_ISSUE.AMPERSAND_REPAIRED, "a bare & was read as &amp;", { line });
181
- }
182
- : undefined,
183
- surrogatePair: booleanOption("pairSurrogateReferences", options?.pairSurrogateReferences, false)
184
- ? (line): void => {
185
- report.warning(
186
- "parse-error",
187
- XGMML_ISSUE.SURROGATE_PAIRED,
188
- "two surrogate character references were joined into one character",
189
- { line },
190
- );
191
- }
192
- : undefined,
193
- };
177
+ const repairs = repairsOf(options, report);
194
178
  const parser = new XgmmlParser(report);
195
179
  const seen = { content: false };
196
180
  try {
@@ -200,12 +184,7 @@ export async function parseXgmml(
200
184
  repairs,
201
185
  );
202
186
  } catch (err) {
203
- if (err instanceof XmlSyntaxError) {
204
- if (!seen.content) {
205
- report.fail(XGMML_ISSUE.EMPTY_INPUT, "the input is empty");
206
- }
207
- report.fail(XGMML_ISSUE.XML_SYNTAX, err.message, { line: err.line });
208
- }
187
+ failOnSyntax(err, seen.content, report);
209
188
  throw err;
210
189
  }
211
190
  const doc = parser.document();
@@ -220,6 +199,49 @@ export async function parseXgmml(
220
199
  return doc;
221
200
  }
222
201
 
202
+ /**
203
+ * The XML repairs the options switch on, each reporting where it repaired.
204
+ * @param options - the XGMML options
205
+ * @param report - the report
206
+ * @returns the repairs
207
+ */
208
+ function repairsOf(options: XgmmlImportOptions | undefined, report: ImportReportBuilder): XmlRepairs {
209
+ return {
210
+ bareAmpersand: booleanOption("repairBareAmpersands", options?.repairBareAmpersands, false)
211
+ ? (line): void => {
212
+ report.warning("parse-error", XGMML_ISSUE.AMPERSAND_REPAIRED, "a bare & was read as &amp;", { line });
213
+ }
214
+ : undefined,
215
+ surrogatePair: booleanOption("pairSurrogateReferences", options?.pairSurrogateReferences, false)
216
+ ? (line): void => {
217
+ report.warning(
218
+ "parse-error",
219
+ XGMML_ISSUE.SURROGATE_PAIRED,
220
+ "two surrogate character references were joined into one character",
221
+ { line },
222
+ );
223
+ }
224
+ : undefined,
225
+ };
226
+ }
227
+
228
+ /**
229
+ * Fail the report on an XML syntax error: an input with no content is empty, any other is
230
+ * malformed. Any other error is left to the caller.
231
+ * @param err - the error the tokenizer threw
232
+ * @param content - whether non-whitespace text was seen
233
+ * @param report - the report
234
+ */
235
+ function failOnSyntax(err: unknown, content: boolean, report: ImportReportBuilder): void {
236
+ if (!(err instanceof XmlSyntaxError)) {
237
+ return;
238
+ }
239
+ if (!content) {
240
+ report.fail(XGMML_ISSUE.EMPTY_INPUT, "the input is empty");
241
+ }
242
+ report.fail(XGMML_ISSUE.XML_SYNTAX, err.message, { line: err.line });
243
+ }
244
+
223
245
  /**
224
246
  * Pass text chunks through while noting non-whitespace content.
225
247
  * @param chunks - the chunks
package/src/sniff.ts CHANGED
@@ -356,40 +356,57 @@ function skeletonOf(text: string): unknown {
356
356
  }
357
357
  const root: Record<string, unknown> = {};
358
358
  for (const key of rootKeys) {
359
- switch (key) {
360
- case "graph":
361
- case "options":
362
- root[key] = objectOf(keys.get(key));
363
- break;
364
- case "graphs": {
365
- // the keys of any node or edge of the first graph: OBO Graphs or JGF (design 1.6)
366
- const nodes = keys.get("graphs[0].nodes[]");
367
- const edges = keys.get("graphs[0].edges[]");
368
- const graph: Record<string, unknown> = {};
369
- if (nodes !== undefined) {
370
- graph.nodes = [objectOf(nodes)];
371
- }
372
- if (edges !== undefined) {
373
- graph.edges = [objectOf(edges)];
374
- }
375
- root[key] = nodes === undefined && edges === undefined ? [] : [graph];
376
- break;
377
- }
378
- case "nodes":
379
- case "edges":
380
- case "links": {
381
- const first = keys.get(`${key}[0]`);
382
- root[key] = first === undefined ? [] : [objectOf(first)];
383
- break;
384
- }
385
- default:
386
- root[key] = true;
387
- break;
388
- }
359
+ root[key] = placeholderOf(key, keys);
389
360
  }
390
361
  return root;
391
362
  }
392
363
 
364
+ /**
365
+ * The placeholder value of a root key: the shape the dialect rule tests that key for.
366
+ * @param key - the root key
367
+ * @param keys - the key sets by path
368
+ * @returns the placeholder
369
+ */
370
+ function placeholderOf(key: string, keys: ReadonlyMap<KeyPath, Set<string>>): unknown {
371
+ switch (key) {
372
+ case "graph":
373
+ case "options":
374
+ return objectOf(keys.get(key));
375
+ case "graphs":
376
+ return graphsPlaceholder(keys);
377
+ case "nodes":
378
+ case "edges":
379
+ case "links": {
380
+ const first = keys.get(`${key}[0]`);
381
+ return first === undefined ? [] : [objectOf(first)];
382
+ }
383
+ default:
384
+ return true;
385
+ }
386
+ }
387
+
388
+ /**
389
+ * The placeholder of `graphs`: the keys of any node or edge of the first graph, which tell OBO
390
+ * Graphs from JGF (design 1.6).
391
+ * @param keys - the key sets by path
392
+ * @returns `[]` when neither was seen, else one graph holding them
393
+ */
394
+ function graphsPlaceholder(keys: ReadonlyMap<KeyPath, Set<string>>): unknown[] {
395
+ const nodes = keys.get("graphs[0].nodes[]");
396
+ const edges = keys.get("graphs[0].edges[]");
397
+ if (nodes === undefined && edges === undefined) {
398
+ return [];
399
+ }
400
+ const graph: Record<string, unknown> = {};
401
+ if (nodes !== undefined) {
402
+ graph.nodes = [objectOf(nodes)];
403
+ }
404
+ if (edges !== undefined) {
405
+ graph.edges = [objectOf(edges)];
406
+ }
407
+ return [graph];
408
+ }
409
+
393
410
  /**
394
411
  * An object holding placeholder values for a key set: `{}` for the keys the rule tests with
395
412
  * isJsonObject (`attributes`, `data`), `true` otherwise.
@@ -424,34 +441,6 @@ function scanKeys(text: string): Map<KeyPath, Set<string>> {
424
441
  const counts: number[] = [];
425
442
  let pendingKey: string | null = null;
426
443
  let expectingKey = false;
427
- const pathOf = (): KeyPath | null => {
428
- const depth = kinds.length;
429
- if (depth === 1) {
430
- return kinds[0] === "object" ? "" : null;
431
- }
432
- if (depth === 2 && kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
433
- return "nodes[0]";
434
- }
435
- if (depth === 2 && kinds[0] === "object" && kinds[1] === "object") {
436
- return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
437
- }
438
- if (
439
- depth === 5 &&
440
- kinds.join() === "object,array,object,array,object" &&
441
- labels[1] === "graphs" &&
442
- labels[2] === "0" &&
443
- (labels[3] === "nodes" || labels[3] === "edges")
444
- ) {
445
- return labels[3] === "nodes" ? "graphs[0].nodes[]" : "graphs[0].edges[]";
446
- }
447
- if (depth === 3 && kinds[0] === "object" && kinds[1] === "array" && kinds[2] === "object") {
448
- const section = labels[1];
449
- if ((section === "nodes" || section === "edges" || section === "links") && labels[2] === "0") {
450
- return `${section}[0]`;
451
- }
452
- }
453
- return null;
454
- };
455
444
  let i = 0;
456
445
  const n = text.length;
457
446
  while (i < n) {
@@ -487,7 +476,7 @@ function scanKeys(text: string): Map<KeyPath, Set<string>> {
487
476
  pendingKey = null;
488
477
  } else if (ch === ":") {
489
478
  if (pendingKey !== null) {
490
- const path = pathOf();
479
+ const path = keyPathOf(kinds, labels);
491
480
  if (path !== null) {
492
481
  let set = found.get(path);
493
482
  if (set === undefined) {
@@ -510,6 +499,73 @@ function scanKeys(text: string): Map<KeyPath, Set<string>> {
510
499
  return found;
511
500
  }
512
501
 
502
+ /**
503
+ * The watched path of the innermost open object, from the container stack.
504
+ * @param kinds - the kind of each open container, outermost first
505
+ * @param labels - the key or index each open container sits under
506
+ * @returns the path, or null when keys there are not watched
507
+ */
508
+ function keyPathOf(kinds: readonly ("object" | "array")[], labels: readonly string[]): KeyPath | null {
509
+ switch (kinds.length) {
510
+ case 1:
511
+ return kinds[0] === "object" ? "" : null;
512
+ case 2:
513
+ return nestedObjectPath(kinds, labels);
514
+ case 3:
515
+ return sectionElementPath(kinds, labels);
516
+ case 5:
517
+ return graphsMemberPath(kinds, labels);
518
+ default:
519
+ return null;
520
+ }
521
+ }
522
+
523
+ /**
524
+ * At depth 2: the first element of a top-level array, or the `graph` / `options` object.
525
+ * @param kinds - the kind of each open container, outermost first
526
+ * @param labels - the key or index each open container sits under
527
+ * @returns the path, or null
528
+ */
529
+ function nestedObjectPath(kinds: readonly ("object" | "array")[], labels: readonly string[]): KeyPath | null {
530
+ if (kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
531
+ return "nodes[0]";
532
+ }
533
+ if (kinds[0] === "object" && kinds[1] === "object") {
534
+ return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
535
+ }
536
+ return null;
537
+ }
538
+
539
+ /**
540
+ * At depth 3: the first element of the root's `nodes`, `edges` or `links` array.
541
+ * @param kinds - the kind of each open container, outermost first
542
+ * @param labels - the key or index each open container sits under
543
+ * @returns the path, or null
544
+ */
545
+ function sectionElementPath(kinds: readonly ("object" | "array")[], labels: readonly string[]): KeyPath | null {
546
+ if (kinds[0] !== "object" || kinds[1] !== "array" || kinds[2] !== "object" || labels[2] !== "0") {
547
+ return null;
548
+ }
549
+ const section = labels[1];
550
+ return section === "nodes" || section === "edges" || section === "links" ? `${section}[0]` : null;
551
+ }
552
+
553
+ /**
554
+ * At depth 5: any node or edge of the first graph of the root's `graphs` array.
555
+ * @param kinds - the kind of each open container, outermost first
556
+ * @param labels - the key or index each open container sits under
557
+ * @returns the path, or null
558
+ */
559
+ function graphsMemberPath(kinds: readonly ("object" | "array")[], labels: readonly string[]): KeyPath | null {
560
+ if (kinds.join() !== "object,array,object,array,object" || labels[1] !== "graphs" || labels[2] !== "0") {
561
+ return null;
562
+ }
563
+ if (labels[3] === "nodes") {
564
+ return "graphs[0].nodes[]";
565
+ }
566
+ return labels[3] === "edges" ? "graphs[0].edges[]" : null;
567
+ }
568
+
513
569
  /**
514
570
  * The index of the closing quote of a JSON string starting after its opening quote.
515
571
  * @param text - the text
@@ -1 +0,0 @@
1
- {"version":3,"file":"children-CL3Cy0ez.js","sources":["../../src/children.ts"],"sourcesContent":["/**\n * The children CSR over a containment column: containment\n * (GEXF `pid` / `<parents>`, Cytoscape `parent`, DOT clusters, GraphML nested graphs) is a node\n * column with the `parent` role (u32, refersTo node) or the `parents` role (list of u32) and never\n * enters the CSR of the snapshot. Importers and exporters that need to walk containers top-down\n * (nested subgraphs, cluster blocks, parent lists) build this inverse index once: for every node\n * `u`, `children[rowPtr[u] .. rowPtr[u + 1])` are its children in ascending index order, `roots`\n * are the nodes with no parent, and `depthFirst()` is the pre-order the nested writers use.\n *\n * The helper is deliberately outside the core (7.1: it computes a property the arrays do not\n * already imply and only io needs it). A reference is ignored when it is unset, INVALID_INDEX, out\n * of range, or the node itself; a cycle (a parent chain that never reaches a root) is reported\n * through `unreachable` and its members are appended to the depth-first order in index order so\n * every node is written exactly once.\n */\n\nimport { type Column, type GraphSnapshot, INVALID_INDEX } from \"@graphty/graph-format\";\n\n/**\n * The role of the column a children CSR is built over.\n * @category Plugin helpers\n */\nexport type ContainmentRole = \"parent\" | \"parents\";\n\n/**\n * How the CSR is built: from a role column of the snapshot (default `parent`, then `parents`) or an explicit column.\n * @category Plugin helpers\n */\nexport interface ChildrenOptions {\n /**\n * The column to read: a role name (`parent` for the u32 single-parent column, `parents` for\n * the list column) or a column object of either shape; \"auto\" (default) takes the `parent`\n * role column when the snapshot has one, else `parents`, else no containment; null builds\n * the empty CSR (every node a root) whatever the snapshot holds.\n */\n readonly column?: ContainmentRole | Column | \"auto\" | null | undefined;\n}\n\n/**\n * One depth-first traversal of the containment forest.\n * @category Plugin helpers\n */\nexport interface DepthFirstOrder {\n /** Every node index exactly once: roots in index order, each followed by its descendants, cycle members last. */\n readonly order: Uint32Array;\n /** The depth of every node in the traversal (0 for a root or a cycle member forced to the top). */\n readonly depth: Uint32Array;\n /** Whether `order` differs from `0..n-1`. */\n readonly reordered: boolean;\n}\n\n/**\n * The children CSR of a snapshot's containment column: the inverse\n * of the parent relation as a compressed sparse row structure over node indices.\n * @category Plugin helpers\n */\nexport class ChildrenCsr {\n /** The number of nodes (the row count of the CSR). */\n readonly nodeCount: number;\n /** `rowPtr[u] .. rowPtr[u + 1]` is the range of `children` holding the children of `u`; length nodeCount + 1. */\n readonly rowPtr: Uint32Array;\n /** Child node indices, ascending within each parent's range. */\n readonly children: Uint32Array;\n /** The nodes with no (valid) parent, in index order. */\n readonly roots: Uint32Array;\n /** Every (child, parent) reference kept; equal to `children.length`. */\n readonly edgeCount: number;\n /** References dropped because they were INVALID_INDEX, out of range or self-references. */\n readonly dropped: number;\n /** Nodes whose parent chain never reaches a root (members of a cycle), counted once each. */\n readonly unreachable: number;\n /** The column the CSR was built from, or null when the snapshot has no containment. */\n readonly column: Column | null;\n\n private readonly parentCount: Uint32Array;\n\n /**\n * Build the CSR; use childrenCsr() rather than the constructor.\n * @param nodeCount - the node count\n * @param rowPtr - the row pointers\n * @param children - the child list\n * @param parentCount - parents per node (0 for a root)\n * @param dropped - references ignored\n * @param column - the source column, or null\n */\n constructor(\n nodeCount: number,\n rowPtr: Uint32Array,\n children: Uint32Array,\n parentCount: Uint32Array,\n dropped: number,\n column: Column | null,\n ) {\n this.nodeCount = nodeCount;\n this.rowPtr = rowPtr;\n this.children = children;\n this.parentCount = parentCount;\n this.edgeCount = children.length;\n this.dropped = dropped;\n this.column = column;\n let rootCount = 0;\n for (let u = 0; u < nodeCount; u++) {\n if (parentCount[u] === 0) {\n rootCount++;\n }\n }\n const roots = new Uint32Array(rootCount);\n let r = 0;\n for (let u = 0; u < nodeCount; u++) {\n if (parentCount[u] === 0) {\n roots[r++] = u;\n }\n }\n this.roots = roots;\n this.unreachable = nodeCount - this.reachableCount();\n }\n\n /**\n * The children of a node, as a view into `children` (do not modify).\n * @param node - the node index\n * @returns the child indices in ascending order; empty for a leaf\n */\n childrenOf(node: number): Uint32Array {\n return this.children.subarray(this.rowPtr[node], this.rowPtr[node + 1]);\n }\n\n /**\n * How many children a node has.\n * @param node - the node index\n * @returns the count\n */\n childCount(node: number): number {\n return this.rowPtr[node + 1] - this.rowPtr[node];\n }\n\n /**\n * Whether a node is a container (has at least one child).\n * @param node - the node index\n * @returns true when it has children\n */\n hasChildren(node: number): boolean {\n return this.rowPtr[node + 1] > this.rowPtr[node];\n }\n\n /**\n * How many parents a node has: 0 for a root, 1 under a `parent` column, any number under `parents`.\n * @param node - the node index\n * @returns the parent count\n */\n parentCountOf(node: number): number {\n return this.parentCount[node];\n }\n\n /**\n * Whether a node has no parent.\n * @param node - the node index\n * @returns true for a root\n */\n isRoot(node: number): boolean {\n return this.parentCount[node] === 0;\n }\n\n /**\n * Whether the snapshot has any containment at all.\n * @returns true when at least one child reference was kept\n */\n isEmpty(): boolean {\n return this.edgeCount === 0;\n }\n\n /**\n * A pre-order depth-first traversal from the roots in index order (children in ascending\n * order), then every node not yet visited (a cycle member, or a multi-parent node reached\n * only through a cycle) in index order at depth 0. Each node appears exactly once, so nested\n * writers emit every element once even for a `parents` column that shares a child.\n * @returns the order, the depth of every node and whether the order differs from index order\n */\n depthFirst(): DepthFirstOrder {\n const n = this.nodeCount;\n const order = new Uint32Array(n);\n const depth = new Uint32Array(n);\n const visited = new Uint8Array(n);\n const stackNode: number[] = [];\n const stackCursor: number[] = [];\n let position = 0;\n let reordered = false;\n const place = (u: number, d: number): void => {\n visited[u] = 1;\n if (u !== position) {\n reordered = true;\n }\n order[position++] = u;\n depth[u] = d;\n };\n const visit = (root: number): void => {\n place(root, 0);\n stackNode.push(root);\n stackCursor.push(this.rowPtr[root]);\n while (stackNode.length > 0) {\n const top = stackNode.length - 1;\n const u = stackNode[top];\n const cursor = stackCursor[top];\n if (cursor >= this.rowPtr[u + 1]) {\n stackNode.pop();\n stackCursor.pop();\n continue;\n }\n stackCursor[top] = cursor + 1;\n const v = this.children[cursor];\n if (visited[v] === 1) {\n continue;\n }\n place(v, stackNode.length);\n stackNode.push(v);\n stackCursor.push(this.rowPtr[v]);\n }\n };\n for (const root of this.roots) {\n visit(root);\n }\n for (let u = 0; u < n; u++) {\n if (visited[u] === 0) {\n visit(u);\n }\n }\n return { order, depth, reordered };\n }\n\n /**\n * The nodes reachable from the roots by following child references.\n * @returns how many nodes a traversal from the roots reaches\n */\n private reachableCount(): number {\n const visited = new Uint8Array(this.nodeCount);\n // every node is pushed at most once, so a stack of nodeCount entries never overflows\n const stack = new Uint32Array(this.nodeCount);\n let top = 0;\n let count = 0;\n for (const root of this.roots) {\n visited[root] = 1;\n count++;\n stack[top++] = root;\n while (top > 0) {\n const u = stack[--top];\n for (let k = this.rowPtr[u]; k < this.rowPtr[u + 1]; k++) {\n const v = this.children[k];\n if (visited[v] === 0) {\n visited[v] = 1;\n count++;\n stack[top++] = v;\n }\n }\n }\n }\n return count;\n }\n}\n\n/**\n * Build the children CSR of a snapshot.\n * @param snapshot - the snapshot\n * @param options - which column to read; the `parent` role, then `parents`, by default\n * @returns the CSR; empty (every node a root) when the snapshot has no containment column\n * @category Plugin helpers\n */\nexport function childrenCsr(snapshot: GraphSnapshot, options: ChildrenOptions = {}): ChildrenCsr {\n const column = resolveColumn(snapshot, options.column === undefined ? \"auto\" : options.column);\n return childrenFromColumn(snapshot.nodeCount, column);\n}\n\n/**\n * Build the children CSR over one containment column without a snapshot (an importer that holds\n * the column before freezing, a test).\n * @param nodeCount - the node count the references index into\n * @param column - a u32 `parent`-shaped column, a list-of-u32 `parents`-shaped column, or null for none\n * @returns the CSR\n * @category Plugin helpers\n */\nexport function childrenFromColumn(nodeCount: number, column: Column | null): ChildrenCsr {\n const rowPtr = new Uint32Array(nodeCount + 1);\n const parentCount = new Uint32Array(nodeCount);\n let dropped = 0;\n const references: number[] = [];\n if (column !== null) {\n const rows = Math.min(column.length, nodeCount);\n const keep = (child: number, parent: number): void => {\n if (!Number.isInteger(parent) || parent === INVALID_INDEX || parent >= nodeCount || parent === child) {\n dropped++;\n return;\n }\n references.push(child, parent);\n rowPtr[parent + 1]++;\n parentCount[child]++;\n };\n if (column.dtype === \"u32\") {\n const { data } = column;\n for (let i = 0; i < rows; i++) {\n if (column.isSet(i)) {\n keep(i, data[i]);\n }\n }\n } else if (column.dtype === \"list\") {\n for (let i = 0; i < rows; i++) {\n if (!column.isSet(i)) {\n continue;\n }\n for (const item of column.sliceOf(i)) {\n if (typeof item === \"number\") {\n keep(i, item);\n } else {\n dropped++;\n }\n }\n }\n } else {\n throw new TypeError(\n `a containment column must be u32 or a list of u32, found ${column.dtype} column \"${column.meta.name}\"`,\n );\n }\n }\n for (let u = 0; u < nodeCount; u++) {\n rowPtr[u + 1] += rowPtr[u];\n }\n const children = new Uint32Array(rowPtr[nodeCount]);\n const fill = rowPtr.slice(0, nodeCount);\n // references were collected in ascending child order, so each parent's range fills ascending\n for (let k = 0; k < references.length; k += 2) {\n children[fill[references[k + 1]]++] = references[k];\n }\n return new ChildrenCsr(nodeCount, rowPtr, children, parentCount, dropped, column);\n}\n\n/**\n * The column a ChildrenOptions selects.\n * @param snapshot - the snapshot\n * @param choice - the option value\n * @returns the column, or null when the snapshot has none of that shape\n */\nfunction resolveColumn(snapshot: GraphSnapshot, choice: ContainmentRole | Column | \"auto\" | null): Column | null {\n if (typeof choice !== \"string\") {\n return choice;\n }\n if (choice === \"parent\" || choice === \"parents\") {\n return snapshot.nodes.byRole(choice);\n }\n return snapshot.nodes.byRole(\"parent\") ?? snapshot.nodes.byRole(\"parents\");\n}\n"],"names":[],"mappings":"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"}