@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
@@ -1,9 +1,9 @@
1
1
  import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
2
- import { c as capabilities, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, o as DUPLICATE_ATTRIBUTE_CODE, g as UNKNOWN_ELEMENT_CODE, b5 as EMPTY_COLUMN_DROPPED_CODE, ai as PARENT_CYCLE_CODE, P as PRECISION_CODE, w as UNKNOWN_ENCODING_CODE, a2 as JSON_NONSTANDARD_NUMBER_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, O as OPTION_IGNORED_CODE, S as SINK_OPTION_CODE, H as HYPEREDGE_CODE, ad as TOO_LARGE_CODE, i as DANGLING_REFERENCE_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, I as ID_MERGED_CODE, m as DUPLICATE_EDGE_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, a3 as BAD_VALUE_CODE, s as MISSING_ENDPOINT_CODE, t as MISSING_ID_CODE, ak as SYNTAX_CODE, E as EMPTY_INPUT_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, bB as readText, b as plural, ao as reportSinkOptions, an as reportUnusedOptions, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, $ as agree, as as weightFromValue, a0 as uniqueColumnName, a7 as chooseGraph, ap as graphChosen, a1 as declareResolved, aB as GRAPH_COLUMN_AS_METADATA_CODE, aC as TYPEDEF_NODES_CODE, aD as RELATION_ASSUMED_CODE, at as COLUMN_AS_PROPERTY_VALUE_CODE, p as pairFolding, e as explicitWeights, bd as NONFINITE_AS_NULL_CODE, L as LOSS, b3 as DIRECTION_DROPPED_CODE, aA as NODE_ORDER_CODE, r as resolveExportOptions, b_ as otherFormatDialect, a as checkCapabilities, bD as countMixedEdges, aa as formatF32, ab as formatF64 } from "./export-B-aVCwyG.js";
3
- import { M as MAYBE_UNSAFE_INTEGER, j as MAYBE_INEXACT_EXPONENT, l as rewriteNumbers, m as findDuplicateKeys, f as flipY } from "./json-elements-DpO6AXIc.js";
2
+ import { c as capabilities, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, o as DUPLICATE_ATTRIBUTE_CODE, g as UNKNOWN_ELEMENT_CODE, b5 as EMPTY_COLUMN_DROPPED_CODE, ai as PARENT_CYCLE_CODE, P as PRECISION_CODE, w as UNKNOWN_ENCODING_CODE, a2 as JSON_NONSTANDARD_NUMBER_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, O as OPTION_IGNORED_CODE, S as SINK_OPTION_CODE, H as HYPEREDGE_CODE, ad as TOO_LARGE_CODE, i as DANGLING_REFERENCE_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, I as ID_MERGED_CODE, m as DUPLICATE_EDGE_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, a3 as BAD_VALUE_CODE, s as MISSING_ENDPOINT_CODE, t as MISSING_ID_CODE, ak as SYNTAX_CODE, E as EMPTY_INPUT_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, bB as readText, b as plural, ao as reportSinkOptions, an as reportUnusedOptions, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, $ as agree, as as weightFromValue, a0 as uniqueColumnName, a7 as chooseGraph, ap as graphChosen, a1 as declareResolved, aB as GRAPH_COLUMN_AS_METADATA_CODE, aC as TYPEDEF_NODES_CODE, aD as RELATION_ASSUMED_CODE, at as COLUMN_AS_PROPERTY_VALUE_CODE, p as pairFolding, e as explicitWeights, bd as NONFINITE_AS_NULL_CODE, L as LOSS, b3 as DIRECTION_DROPPED_CODE, aA as NODE_ORDER_CODE, r as resolveExportOptions, b_ as otherFormatDialect, a as checkCapabilities, bD as countMixedEdges, aa as formatF32, ab as formatF64 } from "./export-rKLeGQMo.js";
3
+ import { M as MAYBE_UNSAFE_INTEGER, j as MAYBE_INEXACT_EXPONENT, l as rewriteNumbers, m as findDuplicateKeys, f as flipY } from "./json-elements-DKSqpNW1.js";
4
4
  import { j as joinText, e as encodeChunks, i as indentUnit } from "./writer-DxjgHwSe.js";
5
- import { t as trimTrailingZeros } from "./text-Bjfa1xYL.js";
6
- import { d as OBOGRAPHS_PREDICATE_TAGS, g as compactOboIri, o as oboColumnDecl, P as PLACEHOLDER_COLUMN, h as synonymScopeOf, O as OBO_NODE_COLUMNS, c as capabilityNotes, s as slotColumn, e as emptyColumnNotes, j as OBO_PURL, f as framelessNodes, m as movedNodes, U as UNWRITTEN_ROLES, n as notePropertyColumn, a as cellOf, v as valuesOf, k as OBO_IN_OWL, b as fitsVocabulary, t as textOf, S as SYNONYM_SCOPES } from "./ontology-export-50L9DOV4.js";
5
+ import { t as trimTrailingZeros } from "./text-DHOJXnED.js";
6
+ import { d as OBOGRAPHS_PREDICATE_TAGS, g as compactOboIri, o as oboColumnDecl, P as PLACEHOLDER_COLUMN, h as synonymScopeOf, O as OBO_NODE_COLUMNS, c as capabilityNotes, s as slotColumn, e as emptyColumnNotes, j as OBO_PURL, f as framelessNodes, m as movedNodes, U as UNWRITTEN_ROLES, n as notePropertyColumn, a as cellOf, v as valuesOf, k as OBO_IN_OWL, b as fitsVocabulary, t as textOf, S as SYNONYM_SCOPES } from "./ontology-export-CtRXjg_i.js";
7
7
  const JSON_DIALECTS = Object.freeze([
8
8
  "node-link",
9
9
  "d3",
@@ -43,6 +43,10 @@ function sniffJsonDialect(root) {
43
43
  if (!isJsonObject(root)) {
44
44
  return null;
45
45
  }
46
+ const decided = sniffWrapperDialect(root) ?? sniffEdgelessDialect(root);
47
+ return decided === void 0 ? sniffEdgeListDialect(root) : decided;
48
+ }
49
+ function sniffWrapperDialect(root) {
46
50
  if (hasKey(root, "elements")) {
47
51
  return "cytoscape";
48
52
  }
@@ -52,33 +56,42 @@ function sniffJsonDialect(root) {
52
56
  if (Array.isArray(root.graphs)) {
53
57
  return root.graphs.some((g) => isJsonObject(g) && isOboGraph(g)) ? "obographs" : "jgf";
54
58
  }
55
- if (!hasKey(root, "edges") && !hasKey(root, "links")) {
56
- if (hasKey(root, "nodes") && hasKey(root, "adjacency")) {
57
- return "adjacency";
58
- }
59
- if (!hasKey(root, "nodes")) {
60
- return hasKey(root, "children") ? "tree" : null;
61
- }
59
+ return void 0;
60
+ }
61
+ function sniffEdgelessDialect(root) {
62
+ if (hasKey(root, "edges") || hasKey(root, "links")) {
63
+ return void 0;
64
+ }
65
+ if (hasKey(root, "nodes")) {
66
+ return hasKey(root, "adjacency") ? "adjacency" : void 0;
62
67
  }
68
+ return hasKey(root, "children") ? "tree" : null;
69
+ }
70
+ function sniffEdgeListDialect(root) {
63
71
  const firstNode = firstJsonObject(root.nodes);
64
72
  const firstEdge = firstJsonObject(hasKey(root, "edges") ? root.edges : root.links);
65
73
  if (isJsonObject(root.options) && (hasKey(root.options, "type") || hasKey(root.options, "multi"))) {
66
74
  return "graphology";
67
75
  }
68
76
  const networkx = hasKey(root, "links") || hasKey(root, "directed") || hasKey(root, "multigraph") || hasKey(root, "graph");
69
- if (!networkx && firstNode !== null && hasKey(firstNode, "key") && !hasKey(firstNode, "id")) {
77
+ const record = networkx ? void 0 : sniffRecordDialect(firstNode, firstEdge);
78
+ if (record !== void 0) {
79
+ return record;
80
+ }
81
+ const bare = !hasKey(root, "directed") && !hasKey(root, "multigraph") && !hasKey(root, "graph");
82
+ return bare && hasKey(root, "links") ? "d3" : "node-link";
83
+ }
84
+ function sniffRecordDialect(firstNode, firstEdge) {
85
+ if (firstNode !== null && hasKey(firstNode, "key") && !hasKey(firstNode, "id")) {
70
86
  return "graphology";
71
87
  }
72
- if (!networkx && firstEdge !== null && !hasKey(firstEdge, "from")) {
73
- if (hasKey(firstEdge, "undirected") || isJsonObject(firstEdge.attributes)) {
74
- return "graphology";
75
- }
88
+ if (firstEdge === null) {
89
+ return void 0;
76
90
  }
77
- if (!networkx && firstEdge !== null && hasKey(firstEdge, "from") && hasKey(firstEdge, "to") && !hasKey(firstEdge, "source")) {
78
- return "vis";
91
+ if (!hasKey(firstEdge, "from")) {
92
+ return hasKey(firstEdge, "undirected") || isJsonObject(firstEdge.attributes) ? "graphology" : void 0;
79
93
  }
80
- const bare = !hasKey(root, "directed") && !hasKey(root, "multigraph") && !hasKey(root, "graph");
81
- return bare && hasKey(root, "links") ? "d3" : "node-link";
94
+ return hasKey(firstEdge, "to") && !hasKey(firstEdge, "source") ? "vis" : void 0;
82
95
  }
83
96
  const OBOGRAPHS_NODE_TYPES = /* @__PURE__ */ new Set(["CLASS", "INDIVIDUAL", "PROPERTY"]);
84
97
  function isOboGraph(graph) {
@@ -373,38 +386,42 @@ function skeletonOf(text) {
373
386
  }
374
387
  const root = {};
375
388
  for (const key of rootKeys) {
376
- switch (key) {
377
- case "graph":
378
- case "options":
379
- root[key] = objectOf(keys.get(key));
380
- break;
381
- case "graphs": {
382
- const nodes = keys.get("graphs[0].nodes[]");
383
- const edges = keys.get("graphs[0].edges[]");
384
- const graph = {};
385
- if (nodes !== void 0) {
386
- graph.nodes = [objectOf(nodes)];
387
- }
388
- if (edges !== void 0) {
389
- graph.edges = [objectOf(edges)];
390
- }
391
- root[key] = nodes === void 0 && edges === void 0 ? [] : [graph];
392
- break;
393
- }
394
- case "nodes":
395
- case "edges":
396
- case "links": {
397
- const first = keys.get(`${key}[0]`);
398
- root[key] = first === void 0 ? [] : [objectOf(first)];
399
- break;
400
- }
401
- default:
402
- root[key] = true;
403
- break;
404
- }
389
+ root[key] = placeholderOf(key, keys);
405
390
  }
406
391
  return root;
407
392
  }
393
+ function placeholderOf(key, keys) {
394
+ switch (key) {
395
+ case "graph":
396
+ case "options":
397
+ return objectOf(keys.get(key));
398
+ case "graphs":
399
+ return graphsPlaceholder(keys);
400
+ case "nodes":
401
+ case "edges":
402
+ case "links": {
403
+ const first = keys.get(`${key}[0]`);
404
+ return first === void 0 ? [] : [objectOf(first)];
405
+ }
406
+ default:
407
+ return true;
408
+ }
409
+ }
410
+ function graphsPlaceholder(keys) {
411
+ const nodes = keys.get("graphs[0].nodes[]");
412
+ const edges = keys.get("graphs[0].edges[]");
413
+ if (nodes === void 0 && edges === void 0) {
414
+ return [];
415
+ }
416
+ const graph = {};
417
+ if (nodes !== void 0) {
418
+ graph.nodes = [objectOf(nodes)];
419
+ }
420
+ if (edges !== void 0) {
421
+ graph.edges = [objectOf(edges)];
422
+ }
423
+ return [graph];
424
+ }
408
425
  function objectOf(names) {
409
426
  const out = {};
410
427
  if (names !== void 0) {
@@ -421,28 +438,6 @@ function scanKeys(text) {
421
438
  const counts = [];
422
439
  let pendingKey = null;
423
440
  let expectingKey = false;
424
- const pathOf = () => {
425
- const depth = kinds.length;
426
- if (depth === 1) {
427
- return kinds[0] === "object" ? "" : null;
428
- }
429
- if (depth === 2 && kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
430
- return "nodes[0]";
431
- }
432
- if (depth === 2 && kinds[0] === "object" && kinds[1] === "object") {
433
- return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
434
- }
435
- if (depth === 5 && kinds.join() === "object,array,object,array,object" && labels[1] === "graphs" && labels[2] === "0" && (labels[3] === "nodes" || labels[3] === "edges")) {
436
- return labels[3] === "nodes" ? "graphs[0].nodes[]" : "graphs[0].edges[]";
437
- }
438
- if (depth === 3 && kinds[0] === "object" && kinds[1] === "array" && kinds[2] === "object") {
439
- const section = labels[1];
440
- if ((section === "nodes" || section === "edges" || section === "links") && labels[2] === "0") {
441
- return `${section}[0]`;
442
- }
443
- }
444
- return null;
445
- };
446
441
  let i = 0;
447
442
  const n = text.length;
448
443
  while (i < n) {
@@ -478,7 +473,7 @@ function scanKeys(text) {
478
473
  pendingKey = null;
479
474
  } else if (ch === ":") {
480
475
  if (pendingKey !== null) {
481
- const path = pathOf();
476
+ const path = keyPathOf(kinds, labels);
482
477
  if (path !== null) {
483
478
  let set = found.get(path);
484
479
  if (set === void 0) {
@@ -500,6 +495,45 @@ function scanKeys(text) {
500
495
  }
501
496
  return found;
502
497
  }
498
+ function keyPathOf(kinds, labels) {
499
+ switch (kinds.length) {
500
+ case 1:
501
+ return kinds[0] === "object" ? "" : null;
502
+ case 2:
503
+ return nestedObjectPath(kinds, labels);
504
+ case 3:
505
+ return sectionElementPath(kinds, labels);
506
+ case 5:
507
+ return graphsMemberPath(kinds, labels);
508
+ default:
509
+ return null;
510
+ }
511
+ }
512
+ function nestedObjectPath(kinds, labels) {
513
+ if (kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
514
+ return "nodes[0]";
515
+ }
516
+ if (kinds[0] === "object" && kinds[1] === "object") {
517
+ return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
518
+ }
519
+ return null;
520
+ }
521
+ function sectionElementPath(kinds, labels) {
522
+ if (kinds[0] !== "object" || kinds[1] !== "array" || kinds[2] !== "object" || labels[2] !== "0") {
523
+ return null;
524
+ }
525
+ const section = labels[1];
526
+ return section === "nodes" || section === "edges" || section === "links" ? `${section}[0]` : null;
527
+ }
528
+ function graphsMemberPath(kinds, labels) {
529
+ if (kinds.join() !== "object,array,object,array,object" || labels[1] !== "graphs" || labels[2] !== "0") {
530
+ return null;
531
+ }
532
+ if (labels[3] === "nodes") {
533
+ return "graphs[0].nodes[]";
534
+ }
535
+ return labels[3] === "edges" ? "graphs[0].edges[]" : null;
536
+ }
503
537
  function scanString(text, from) {
504
538
  let i = from;
505
539
  while (i < text.length) {
@@ -2076,18 +2110,7 @@ function importAdjacency(ctx, root) {
2076
2110
  const multigraph = hasKey(root, "multigraph") ? flagOf(root.multigraph, "multigraph", false, report) : null;
2077
2111
  ctx.setHeader(directed);
2078
2112
  ctx.writeGraphDict(isPairList(root.graph) ? Object.fromEntries(root.graph) : root.graph, "graph");
2079
- for (const key of Object.keys(root)) {
2080
- if (key !== "nodes" && key !== "adjacency" && key !== "directed" && key !== "multigraph" && key !== "graph") {
2081
- report.warning(
2082
- "unsupported",
2083
- JSON_ISSUE.UNREAD_KEY,
2084
- `top-level key ${key} (${describe(root[key])}) is not read; dropped`,
2085
- {
2086
- element: key
2087
- }
2088
- );
2089
- }
2090
- }
2113
+ reportUnreadAdjacencyKeys(ctx, root);
2091
2114
  const lists = adjacency ?? [];
2092
2115
  ctx.sink.reserve(
2093
2116
  nodes.length,
@@ -2095,90 +2118,120 @@ function importAdjacency(ctx, root) {
2095
2118
  );
2096
2119
  const idKey = ctx.json.nodeIdKey ?? "id";
2097
2120
  ctx.reportNodeIdFrom("adjacency", `the ${JSON.stringify(idKey)} key`);
2098
- const owners = [];
2099
- for (let i = 0; i < nodes.length; i++) {
2100
- const element = `nodes[${i}]`;
2101
- const record = nodes[i];
2102
- let pushed = null;
2103
- if (!isJsonObject(record)) {
2104
- ctx.badElement("node", element);
2105
- } else {
2106
- const id = ctx.coerceId(hasKey(record, idKey) ? record[idKey] : void 0, element);
2107
- if (id === null) {
2108
- ctx.countSkipped("node");
2109
- } else {
2110
- const index = ctx.pushNode(id, element);
2111
- if (index >= 0) {
2112
- pushed = id;
2113
- writeFlat(ctx.nodes, index, record, id, (key) => key !== idKey);
2114
- }
2115
- }
2116
- }
2117
- owners.push(pushed);
2118
- }
2121
+ const owners = nodes.map((record, i) => pushAdjacencyNode(ctx, record, `nodes[${i}]`, idKey));
2119
2122
  throwIfAborted(ctx.options.signal);
2120
- const kind = ctx.uniformKind();
2121
- const { weightFrom } = ctx.options;
2122
- const pending = /* @__PURE__ */ new Map();
2123
- let disagreeing = 0;
2123
+ const reading = {
2124
+ owners,
2125
+ nodeCount: nodes.length,
2126
+ directed,
2127
+ kind: ctx.uniformKind(),
2128
+ idKey,
2129
+ // undirected: entries read once whose mirror is still to come, by pair and key, with their attributes
2130
+ pending: /* @__PURE__ */ new Map(),
2131
+ disagreeing: 0
2132
+ };
2124
2133
  for (let i = 0; i < lists.length; i++) {
2125
- const element = `adjacency[${i}]`;
2126
- const list = lists[i];
2127
- if (!Array.isArray(list)) {
2128
- report.error("validation-error", JSON_ISSUE.BAD_ELEMENT, `${element} is not an array`, { element });
2129
- continue;
2130
- }
2131
- const source = i < owners.length ? owners[i] : null;
2132
- if (source === null) {
2133
- const why = i < nodes.length ? `nodes[${i}] was skipped` : `there is no nodes[${i}]`;
2134
- report.error(
2135
- "missing-value",
2136
- JSON_ISSUE.BAD_INDEX,
2137
- `${element}: ${why}; its ${list.length} edge${plural(list.length)} ${agree(list.length, "is", "are")} skipped`,
2134
+ readAdjacencyList(ctx, reading, i, lists[i]);
2135
+ }
2136
+ reportAdjacencyShape(
2137
+ ctx,
2138
+ nodes.length,
2139
+ adjacency === null ? null : lists.length,
2140
+ reading.disagreeing,
2141
+ reading.pending
2142
+ );
2143
+ ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
2144
+ }
2145
+ const ADJACENCY_DOCUMENT_KEYS = /* @__PURE__ */ new Set(["nodes", "adjacency", "directed", "multigraph", "graph"]);
2146
+ function reportUnreadAdjacencyKeys(ctx, root) {
2147
+ for (const key of Object.keys(root)) {
2148
+ if (!ADJACENCY_DOCUMENT_KEYS.has(key)) {
2149
+ ctx.report.warning(
2150
+ "unsupported",
2151
+ JSON_ISSUE.UNREAD_KEY,
2152
+ `top-level key ${key} (${describe(root[key])}) is not read; dropped`,
2138
2153
  {
2139
- element
2154
+ element: key
2140
2155
  }
2141
2156
  );
2142
- report.counts.skippedEdges += list.length;
2143
- continue;
2144
2157
  }
2145
- for (let j = 0; j < list.length; j++) {
2146
- const entry = `${element}[${j}]`;
2147
- const record = list[j];
2148
- if (!isJsonObject(record)) {
2149
- ctx.badElement("edge", entry);
2150
- continue;
2158
+ }
2159
+ }
2160
+ function pushAdjacencyNode(ctx, record, element, idKey) {
2161
+ if (!isJsonObject(record)) {
2162
+ ctx.badElement("node", element);
2163
+ return null;
2164
+ }
2165
+ const id = ctx.coerceId(hasKey(record, idKey) ? record[idKey] : void 0, element);
2166
+ if (id === null) {
2167
+ ctx.countSkipped("node");
2168
+ return null;
2169
+ }
2170
+ const index = ctx.pushNode(id, element);
2171
+ if (index < 0) {
2172
+ return null;
2173
+ }
2174
+ writeFlat(ctx.nodes, index, record, id, (key) => key !== idKey);
2175
+ return id;
2176
+ }
2177
+ function readAdjacencyList(ctx, reading, i, list) {
2178
+ const { report } = ctx;
2179
+ const element = `adjacency[${i}]`;
2180
+ if (!Array.isArray(list)) {
2181
+ report.error("validation-error", JSON_ISSUE.BAD_ELEMENT, `${element} is not an array`, { element });
2182
+ return;
2183
+ }
2184
+ const source = i < reading.owners.length ? reading.owners[i] : null;
2185
+ if (source === null) {
2186
+ const why = i < reading.nodeCount ? `nodes[${i}] was skipped` : `there is no nodes[${i}]`;
2187
+ report.error(
2188
+ "missing-value",
2189
+ JSON_ISSUE.BAD_INDEX,
2190
+ `${element}: ${why}; its ${list.length} edge${plural(list.length)} ${agree(list.length, "is", "are")} skipped`,
2191
+ {
2192
+ element
2151
2193
  }
2152
- if (!hasKey(record, idKey)) {
2153
- ctx.missingEndpoint(entry, idKey);
2154
- continue;
2194
+ );
2195
+ report.counts.skippedEdges += list.length;
2196
+ return;
2197
+ }
2198
+ for (let j = 0; j < list.length; j++) {
2199
+ readAdjacencyEntry(ctx, reading, source, list[j], element, `${element}[${j}]`);
2200
+ }
2201
+ }
2202
+ function readAdjacencyEntry(ctx, reading, source, record, element, entry) {
2203
+ const { idKey } = reading;
2204
+ if (!isJsonObject(record)) {
2205
+ ctx.badElement("edge", entry);
2206
+ return;
2207
+ }
2208
+ if (!hasKey(record, idKey)) {
2209
+ ctx.missingEndpoint(entry, idKey);
2210
+ return;
2211
+ }
2212
+ try {
2213
+ const target = ctx.coerceId(record[idKey], `${entry}.${idKey}`);
2214
+ if (target === null) {
2215
+ ctx.countSkipped("edge");
2216
+ return;
2217
+ }
2218
+ if (!reading.directed) {
2219
+ const mirror = mirroredEntry(reading.pending, source, target, record, idKey);
2220
+ reading.disagreeing += mirror === "disagrees" ? 1 : 0;
2221
+ if (mirror !== "new") {
2222
+ return;
2155
2223
  }
2156
- try {
2157
- const target = ctx.coerceId(record[idKey], `${entry}.${idKey}`);
2158
- if (target === null) {
2159
- ctx.countSkipped("edge");
2160
- continue;
2161
- }
2162
- if (!directed) {
2163
- const mirror = mirroredEntry(pending, source, target, record, idKey);
2164
- disagreeing += mirror === "disagrees" ? 1 : 0;
2165
- if (mirror !== "new") {
2166
- continue;
2167
- }
2168
- }
2169
- const edge = ctx.pushEdge(source, target, kind, ctx.weightOf(record), entry);
2170
- for (const key of Object.keys(record)) {
2171
- if (key !== idKey && key !== weightFrom) {
2172
- ctx.edges.write(edge, key, record[key], SUFFIX.data, element);
2173
- }
2174
- }
2175
- } catch (err) {
2176
- ctx.skip(err, "edge", entry);
2224
+ }
2225
+ const edge = ctx.pushEdge(source, target, reading.kind, ctx.weightOf(record), entry);
2226
+ const { weightFrom } = ctx.options;
2227
+ for (const key of Object.keys(record)) {
2228
+ if (key !== idKey && key !== weightFrom) {
2229
+ ctx.edges.write(edge, key, record[key], SUFFIX.data, element);
2177
2230
  }
2178
2231
  }
2232
+ } catch (err) {
2233
+ ctx.skip(err, "edge", entry);
2179
2234
  }
2180
- reportAdjacencyShape(ctx, nodes.length, adjacency === null ? null : lists.length, disagreeing, pending);
2181
- ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
2182
2235
  }
2183
2236
  function reportAdjacencyShape(ctx, nodes, lists, disagreeing, pending) {
2184
2237
  const { report } = ctx;
@@ -2298,107 +2351,120 @@ function importGraphology(ctx, root) {
2298
2351
  element: "options"
2299
2352
  });
2300
2353
  }
2301
- let type;
2302
- if (options.type === "directed" || options.type === "undirected" || options.type === "mixed") {
2303
- ({ type } = options);
2304
- } else {
2305
- if (options.type !== void 0 && options.type !== null) {
2306
- report.warning(
2307
- "validation-error",
2308
- JSON_ISSUE.BAD_FLAG,
2309
- `options.type ${describe(options.type)} is not directed, undirected or mixed; mixed assumed`,
2310
- { element: "options.type" }
2311
- );
2312
- }
2313
- type = "mixed";
2314
- }
2315
- let directed;
2316
- if (type === "mixed") {
2317
- const objects = edges.filter((edge) => isJsonObject(edge));
2318
- const undirectedEdges = objects.filter((edge) => edge.undirected === true).length;
2319
- directed = objects.length === 0 ? ctx.defaultDirected("graphology") : undirectedEdges < objects.length;
2320
- } else {
2321
- directed = type === "directed";
2322
- }
2323
- ctx.setHeader(directed);
2354
+ const type = graphologyType(ctx, options);
2355
+ ctx.setHeader(graphologyDirected(ctx, type, edges));
2324
2356
  const multi = hasKey(options, "multi") ? flagOf(options.multi, "options.multi", false, report) : null;
2325
2357
  const allowSelfLoops = hasKey(options, "allowSelfLoops") ? flagOf(options.allowSelfLoops, "options.allowSelfLoops", true, report) : void 0;
2326
2358
  ctx.writeGraphDict(root.attributes, "attributes");
2327
2359
  ctx.reportNodeIdFrom("graphology", "the node key");
2328
2360
  ctx.sink.reserve(nodes.length, edges.length);
2329
2361
  for (let i = 0; i < nodes.length; i++) {
2330
- const element = `nodes[${i}]`;
2331
- const record = nodes[i];
2332
- if (!isJsonObject(record)) {
2333
- ctx.badElement("node", element);
2334
- continue;
2335
- }
2336
- const id = ctx.coerceId(hasKey(record, "key") ? record.key : void 0, element);
2337
- if (id === null) {
2338
- ctx.countSkipped("node");
2339
- continue;
2340
- }
2341
- pushNestedNode(ctx, id, record, "attributes", GRAPHOLOGY_NODE_KEYS, element);
2362
+ pushGraphologyNode(ctx, nodes[i], `nodes[${i}]`);
2342
2363
  }
2343
2364
  throwIfAborted(ctx.options.signal);
2344
- const ids = ctx.declareEdgeIds(edges, (edge) => edge.key, "key", true);
2345
- const violations = { selfLoops: 0, parallels: 0, flags: 0 };
2346
- const pairs = multi === false ? /* @__PURE__ */ new Set() : null;
2365
+ const reading = {
2366
+ ids: ctx.declareEdgeIds(edges, (edge) => edge.key, "key", true),
2367
+ type,
2368
+ allowSelfLoops,
2369
+ // what the edges do against the declared options: graphology itself refuses such a document
2370
+ violations: { selfLoops: 0, parallels: 0, flags: 0 },
2371
+ pairs: multi === false ? /* @__PURE__ */ new Set() : null
2372
+ };
2347
2373
  for (let i = 0; i < edges.length; i++) {
2348
- const element = `edges[${i}]`;
2349
- const record = edges[i];
2350
- if (!isJsonObject(record)) {
2351
- ctx.badElement("edge", element);
2352
- continue;
2374
+ readGraphologyEdge(ctx, reading, edges[i], `edges[${i}]`);
2375
+ }
2376
+ reportGraphologyViolations(ctx, reading.violations, type);
2377
+ ctx.setMeta({ dialect: "graphology", allowSelfLoops }, { declaredMultigraph: multi, ...ctx.weightOriginPatch() });
2378
+ }
2379
+ function graphologyType(ctx, options) {
2380
+ if (options.type === "directed" || options.type === "undirected" || options.type === "mixed") {
2381
+ return options.type;
2382
+ }
2383
+ if (options.type !== void 0 && options.type !== null) {
2384
+ ctx.report.warning(
2385
+ "validation-error",
2386
+ JSON_ISSUE.BAD_FLAG,
2387
+ `options.type ${describe(options.type)} is not directed, undirected or mixed; mixed assumed`,
2388
+ { element: "options.type" }
2389
+ );
2390
+ }
2391
+ return "mixed";
2392
+ }
2393
+ function graphologyDirected(ctx, type, edges) {
2394
+ if (type !== "mixed") {
2395
+ return type === "directed";
2396
+ }
2397
+ const objects = edges.filter((edge) => isJsonObject(edge));
2398
+ const undirectedEdges = objects.filter((edge) => edge.undirected === true).length;
2399
+ return objects.length === 0 ? ctx.defaultDirected("graphology") : undirectedEdges < objects.length;
2400
+ }
2401
+ function pushGraphologyNode(ctx, record, element) {
2402
+ if (!isJsonObject(record)) {
2403
+ ctx.badElement("node", element);
2404
+ return;
2405
+ }
2406
+ const id = ctx.coerceId(hasKey(record, "key") ? record.key : void 0, element);
2407
+ if (id === null) {
2408
+ ctx.countSkipped("node");
2409
+ return;
2410
+ }
2411
+ pushNestedNode(ctx, id, record, "attributes", GRAPHOLOGY_NODE_KEYS, element);
2412
+ }
2413
+ function readGraphologyEdge(ctx, reading, record, element) {
2414
+ if (!isJsonObject(record)) {
2415
+ ctx.badElement("edge", element);
2416
+ return;
2417
+ }
2418
+ if (!present(record, "source") || !present(record, "target")) {
2419
+ ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2420
+ return;
2421
+ }
2422
+ try {
2423
+ const u = ctx.coerceId(record.source, `${element}.source`);
2424
+ const v = ctx.coerceId(record.target, `${element}.target`);
2425
+ if (u === null || v === null) {
2426
+ ctx.countSkipped("edge");
2427
+ return;
2353
2428
  }
2354
- if (!present(record, "source") || !present(record, "target")) {
2355
- ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2356
- continue;
2429
+ const kind = graphologyEdgeKind(ctx, reading, record, element);
2430
+ const attributes = graphologyEdgeAttributes(ctx, record, element);
2431
+ const idValue = ctx.edgeIdValue(reading.ids, record.key);
2432
+ const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(attributes), element);
2433
+ ctx.setEdgeId(reading.ids, edge, idValue);
2434
+ ctx.writeNested(ctx.edges, edge, record, attributes, GRAPHOLOGY_EDGE_KEYS, ctx.options.weightFrom, element);
2435
+ if (reading.allowSelfLoops === false && u === v) {
2436
+ reading.violations.selfLoops++;
2357
2437
  }
2358
- try {
2359
- const u = ctx.coerceId(record.source, `${element}.source`);
2360
- const v = ctx.coerceId(record.target, `${element}.target`);
2361
- if (u === null || v === null) {
2362
- ctx.countSkipped("edge");
2363
- continue;
2364
- }
2365
- let kind;
2366
- if (type === "mixed") {
2367
- kind = flagOf(record.undirected, `${element}.undirected`, false, report) ? "undirected" : "directed";
2368
- } else {
2369
- kind = type;
2370
- if (typeof record.undirected === "boolean" && record.undirected !== (type === "undirected")) {
2371
- violations.flags++;
2372
- }
2373
- }
2374
- const { attributes: rawAttributes } = record;
2375
- if (rawAttributes !== void 0 && rawAttributes !== null && !isJsonObject(rawAttributes)) {
2376
- report.error(
2377
- "validation-error",
2378
- JSON_ISSUE.BAD_VALUE,
2379
- `${element}: attributes must be an object, found ${describe(rawAttributes)}`,
2380
- { element }
2381
- );
2382
- }
2383
- const attributes = isJsonObject(rawAttributes) ? rawAttributes : {};
2384
- const idValue = ctx.edgeIdValue(ids, record.key);
2385
- const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(attributes), element);
2386
- ctx.setEdgeId(ids, edge, idValue);
2387
- ctx.writeNested(ctx.edges, edge, record, attributes, GRAPHOLOGY_EDGE_KEYS, ctx.options.weightFrom, element);
2388
- if (allowSelfLoops === false && u === v) {
2389
- violations.selfLoops++;
2390
- }
2391
- if (pairs !== null) {
2392
- const pair = `${kind} ${pairKey(u, v, kind === "directed")}`;
2393
- violations.parallels += pairs.has(pair) ? 1 : 0;
2394
- pairs.add(pair);
2395
- }
2396
- } catch (err) {
2397
- ctx.skip(err, "edge", element);
2438
+ if (reading.pairs !== null) {
2439
+ const pair = `${kind} ${pairKey(u, v, kind === "directed")}`;
2440
+ reading.violations.parallels += reading.pairs.has(pair) ? 1 : 0;
2441
+ reading.pairs.add(pair);
2398
2442
  }
2443
+ } catch (err) {
2444
+ ctx.skip(err, "edge", element);
2399
2445
  }
2400
- reportGraphologyViolations(ctx, violations, type);
2401
- ctx.setMeta({ dialect: "graphology", allowSelfLoops }, { declaredMultigraph: multi, ...ctx.weightOriginPatch() });
2446
+ }
2447
+ function graphologyEdgeKind(ctx, reading, record, element) {
2448
+ const { type } = reading;
2449
+ if (type === "mixed") {
2450
+ return flagOf(record.undirected, `${element}.undirected`, false, ctx.report) ? "undirected" : "directed";
2451
+ }
2452
+ if (typeof record.undirected === "boolean" && record.undirected !== (type === "undirected")) {
2453
+ reading.violations.flags++;
2454
+ }
2455
+ return type;
2456
+ }
2457
+ function graphologyEdgeAttributes(ctx, record, element) {
2458
+ const { attributes } = record;
2459
+ if (attributes !== void 0 && attributes !== null && !isJsonObject(attributes)) {
2460
+ ctx.report.error(
2461
+ "validation-error",
2462
+ JSON_ISSUE.BAD_VALUE,
2463
+ `${element}: attributes must be an object, found ${describe(attributes)}`,
2464
+ { element }
2465
+ );
2466
+ }
2467
+ return isJsonObject(attributes) ? attributes : {};
2402
2468
  }
2403
2469
  function reportGraphologyViolations(ctx, violations, type) {
2404
2470
  const notes = [];
@@ -2457,23 +2523,7 @@ function importJgf(ctx, root) {
2457
2523
  );
2458
2524
  }
2459
2525
  const nodeRecords = Array.isArray(nodesRaw) ? nodesRaw : Object.values(nodesRaw ?? {});
2460
- let directed;
2461
- if (typeof graph.directed === "boolean") {
2462
- ({ directed } = graph);
2463
- } else if (ctx.explicitDefaultDirected) {
2464
- directed = ctx.options.defaultDirected;
2465
- } else {
2466
- if (graph.directed !== void 0 && graph.directed !== null) {
2467
- report.warning(
2468
- "validation-error",
2469
- JSON_ISSUE.BAD_FLAG,
2470
- `graph.directed is ${describe(graph.directed)}, not a boolean`,
2471
- { element: "graph.directed" }
2472
- );
2473
- }
2474
- const objects = edges.filter((edge) => isJsonObject(edge));
2475
- directed = objects.length === 0 || !objects.every((edge) => edge.directed === false);
2476
- }
2526
+ const directed = jgfDirected(ctx, graph, edges);
2477
2527
  ctx.setHeader(directed);
2478
2528
  ctx.writeGraphDict(graph.metadata, "graph.metadata");
2479
2529
  const shape = {
@@ -2490,44 +2540,73 @@ function importJgf(ctx, root) {
2490
2540
  );
2491
2541
  if (isJsonObject(nodesRaw)) {
2492
2542
  for (const key of Object.keys(nodesRaw)) {
2493
- const element = `nodes[${JSON.stringify(key)}]`;
2494
- const record = nodesRaw[key];
2495
- if (record !== null && !isJsonObject(record)) {
2496
- ctx.badElement("node", element);
2497
- continue;
2498
- }
2499
- const id = ctx.coerceId(key, element);
2500
- if (id === null) {
2501
- ctx.countSkipped("node");
2502
- continue;
2503
- }
2504
- if (record !== null && hasKey(record, "id") && record.id !== key) {
2505
- report.warning(
2506
- "validation-error",
2507
- JSON_ISSUE.INCONSISTENT,
2508
- `${element}: the inner id ${describe(record.id)} differs from the key; the key is the id, the inner one is kept as id${SUFFIX.element}`,
2509
- { element }
2510
- );
2511
- }
2512
- pushJgfNode(ctx, id, record ?? {}, labelColumn, element);
2543
+ pushJgfKeyedNode(ctx, key, nodesRaw[key], labelColumn);
2513
2544
  }
2514
2545
  } else {
2515
2546
  for (let i = 0; i < nodeRecords.length; i++) {
2516
- const element = `nodes[${i}]`;
2517
- const record = nodeRecords[i];
2518
- if (!isJsonObject(record)) {
2519
- ctx.badElement("node", element);
2520
- continue;
2521
- }
2522
- const id = ctx.coerceId(hasKey(record, "id") ? record.id : void 0, element);
2523
- if (id === null) {
2524
- ctx.countSkipped("node");
2525
- continue;
2526
- }
2527
- pushJgfNode(ctx, id, record, labelColumn, element);
2547
+ pushJgfListedNode(ctx, nodeRecords[i], labelColumn, `nodes[${i}]`);
2528
2548
  }
2529
2549
  }
2530
2550
  throwIfAborted(ctx.options.signal);
2551
+ const writeJgfEdge = jgfEdgeWriter(ctx, edges, hyperedges);
2552
+ for (let i = 0; i < edges.length; i++) {
2553
+ readJgfEdge(ctx, edges[i], `edges[${i}]`, directed, writeJgfEdge);
2554
+ }
2555
+ importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
2556
+ ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
2557
+ }
2558
+ function jgfDirected(ctx, graph, edges) {
2559
+ if (typeof graph.directed === "boolean") {
2560
+ return graph.directed;
2561
+ }
2562
+ if (ctx.explicitDefaultDirected) {
2563
+ return ctx.options.defaultDirected;
2564
+ }
2565
+ if (graph.directed !== void 0 && graph.directed !== null) {
2566
+ ctx.report.warning(
2567
+ "validation-error",
2568
+ JSON_ISSUE.BAD_FLAG,
2569
+ `graph.directed is ${describe(graph.directed)}, not a boolean`,
2570
+ { element: "graph.directed" }
2571
+ );
2572
+ }
2573
+ const objects = edges.filter((edge) => isJsonObject(edge));
2574
+ return objects.length === 0 || !objects.every((edge) => edge.directed === false);
2575
+ }
2576
+ function pushJgfKeyedNode(ctx, key, record, labelColumn) {
2577
+ const element = `nodes[${JSON.stringify(key)}]`;
2578
+ if (record !== null && !isJsonObject(record)) {
2579
+ ctx.badElement("node", element);
2580
+ return;
2581
+ }
2582
+ const id = ctx.coerceId(key, element);
2583
+ if (id === null) {
2584
+ ctx.countSkipped("node");
2585
+ return;
2586
+ }
2587
+ if (record !== null && hasKey(record, "id") && record.id !== key) {
2588
+ ctx.report.warning(
2589
+ "validation-error",
2590
+ JSON_ISSUE.INCONSISTENT,
2591
+ `${element}: the inner id ${describe(record.id)} differs from the key; the key is the id, the inner one is kept as id${SUFFIX.element}`,
2592
+ { element }
2593
+ );
2594
+ }
2595
+ pushJgfNode(ctx, id, record ?? {}, labelColumn, element);
2596
+ }
2597
+ function pushJgfListedNode(ctx, record, labelColumn, element) {
2598
+ if (!isJsonObject(record)) {
2599
+ ctx.badElement("node", element);
2600
+ return;
2601
+ }
2602
+ const id = ctx.coerceId(hasKey(record, "id") ? record.id : void 0, element);
2603
+ if (id === null) {
2604
+ ctx.countSkipped("node");
2605
+ return;
2606
+ }
2607
+ pushJgfNode(ctx, id, record, labelColumn, element);
2608
+ }
2609
+ function jgfEdgeWriter(ctx, edges, hyperedges) {
2531
2610
  const ids = ctx.declareEdgeIds([...edges, ...hyperedges], (edge) => edge.id, "id", false);
2532
2611
  const relationColumn = ctx.edges.declareIf(
2533
2612
  { name: "relation", dtype: "string", role: "kind", nullable: true },
@@ -2537,7 +2616,7 @@ function importJgf(ctx, root) {
2537
2616
  { name: "label", dtype: "string", role: "label", nullable: true },
2538
2617
  anyHas(edges, "label") || anyHas(hyperedges, "label")
2539
2618
  );
2540
- const writeJgfEdge = (record, u, v, kind, element, structural = JGF_EDGE_KEYS) => {
2619
+ return (record, u, v, kind, element, structural = JGF_EDGE_KEYS) => {
2541
2620
  const { metadata } = record;
2542
2621
  const dict = isJsonObject(metadata) ? metadata : {};
2543
2622
  const idValue = ctx.edgeIdValue(ids, record.id);
@@ -2546,38 +2625,34 @@ function importJgf(ctx, root) {
2546
2625
  ctx.writeStringField(ctx.edges, relationColumn, edge, record.relation, "relation", element);
2547
2626
  ctx.writeStringField(ctx.edges, edgeLabelColumn, edge, record.label, "label", element);
2548
2627
  if (metadata !== void 0 && metadata !== null && !isJsonObject(metadata)) {
2549
- report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
2628
+ ctx.report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
2550
2629
  element
2551
2630
  });
2552
2631
  }
2553
2632
  ctx.writeNested(ctx.edges, edge, record, dict, structural, ctx.options.weightFrom, element);
2554
2633
  };
2555
- for (let i = 0; i < edges.length; i++) {
2556
- const element = `edges[${i}]`;
2557
- const record = edges[i];
2558
- if (!isJsonObject(record)) {
2559
- ctx.badElement("edge", element);
2560
- continue;
2561
- }
2562
- if (!present(record, "source") || !present(record, "target")) {
2563
- ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2564
- continue;
2565
- }
2566
- try {
2567
- const u = ctx.coerceId(record.source, `${element}.source`);
2568
- const v = ctx.coerceId(record.target, `${element}.target`);
2569
- if (u === null || v === null) {
2570
- ctx.countSkipped("edge");
2571
- continue;
2572
- }
2573
- const edgeDirected = flagOf(record.directed, `${element}.directed`, directed, report);
2574
- writeJgfEdge(record, u, v, edgeDirected ? "directed" : "undirected", element);
2575
- } catch (err) {
2576
- ctx.skip(err, "edge", element);
2634
+ }
2635
+ function readJgfEdge(ctx, record, element, directed, writeJgfEdge) {
2636
+ if (!isJsonObject(record)) {
2637
+ ctx.badElement("edge", element);
2638
+ return;
2639
+ }
2640
+ if (!present(record, "source") || !present(record, "target")) {
2641
+ ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2642
+ return;
2643
+ }
2644
+ try {
2645
+ const u = ctx.coerceId(record.source, `${element}.source`);
2646
+ const v = ctx.coerceId(record.target, `${element}.target`);
2647
+ if (u === null || v === null) {
2648
+ ctx.countSkipped("edge");
2649
+ return;
2577
2650
  }
2651
+ const edgeDirected = flagOf(record.directed, `${element}.directed`, directed, ctx.report);
2652
+ writeJgfEdge(record, u, v, edgeDirected ? "directed" : "undirected", element);
2653
+ } catch (err) {
2654
+ ctx.skip(err, "edge", element);
2578
2655
  }
2579
- importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
2580
- ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
2581
2656
  }
2582
2657
  function jgfGraphOf(ctx, root) {
2583
2658
  const single = isJsonObject(root.graph);
@@ -2832,49 +2907,34 @@ function distinctMembers(ctx, members, element) {
2832
2907
  return distinct;
2833
2908
  }
2834
2909
  function importCytoscape(ctx, root) {
2835
- const { report } = ctx;
2836
- let elements;
2837
- let extra;
2838
- if (Array.isArray(root)) {
2839
- elements = root;
2840
- } else if (isJsonObject(root)) {
2841
- ({ elements } = root);
2842
- ctx.writeGraphDict(root.data, "data");
2843
- const rest = {};
2844
- for (const key of Object.keys(root)) {
2845
- if (key !== "elements" && key !== "data") {
2846
- rest[key] = root[key];
2847
- }
2848
- }
2849
- if (Object.keys(rest).length > 0) {
2850
- extra = rest;
2851
- }
2852
- } else {
2853
- report.fail(JSON_ISSUE.SHAPE, `a Cytoscape document must be an object or an array, found ${describe(root)}`);
2854
- }
2910
+ const { elements, extra } = cytoscapeRoot(ctx, root);
2855
2911
  const { nodes, edges } = cytoscapeSections(ctx, elements);
2856
2912
  ctx.setHeader(ctx.defaultDirected("cytoscape"));
2857
2913
  ctx.reportNodeIdFrom("cytoscape", "data.id");
2858
2914
  ctx.sink.reserve(nodes.length, edges.length);
2859
2915
  const dataHas = (items, key) => items.some((item) => isJsonObject(item) && isJsonObject(item.data) && item.data[key] !== void 0);
2860
- const positionColumn = ctx.nodes.declareIf(
2861
- {
2862
- name: POSITION_COLUMN,
2863
- dtype: "f64",
2864
- components: 3,
2865
- role: "position",
2866
- mutable: true,
2867
- nullable: true,
2868
- // 3D layouts written by Cytoscape-compatible tools carry a z
2869
- extra: { sourceDims: nodes.some(hasPositionZ) ? 3 : 2, units: "file" },
2870
- origin: { format: "json", namespace: "cytoscape" }
2871
- },
2872
- anyHas(nodes, "position")
2873
- );
2874
- const classesColumn = ctx.nodes.declareIf(
2875
- { name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
2876
- anyHas(nodes, "classes")
2877
- );
2916
+ const reading = {
2917
+ positionColumn: ctx.nodes.declareIf(
2918
+ {
2919
+ name: POSITION_COLUMN,
2920
+ dtype: "f64",
2921
+ components: 3,
2922
+ role: "position",
2923
+ mutable: true,
2924
+ nullable: true,
2925
+ // 3D layouts written by Cytoscape-compatible tools carry a z
2926
+ extra: { sourceDims: nodes.some(hasPositionZ) ? 3 : 2, units: "file" },
2927
+ origin: { format: "json", namespace: "cytoscape" }
2928
+ },
2929
+ anyHas(nodes, "position")
2930
+ ),
2931
+ classesColumn: ctx.nodes.declareIf(
2932
+ { name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
2933
+ anyHas(nodes, "classes")
2934
+ ),
2935
+ parents: [],
2936
+ point: [0, 0, 0]
2937
+ };
2878
2938
  const parentColumn = ctx.nodes.declareIf(
2879
2939
  { name: PARENT_COLUMN, dtype: "u32", role: "parent", refersTo: "node", nullable: true },
2880
2940
  dataHas(nodes, "parent")
@@ -2883,77 +2943,104 @@ function importCytoscape(ctx, root) {
2883
2943
  { name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
2884
2944
  anyHas(edges, "classes")
2885
2945
  );
2886
- const parents = [];
2887
- const point = [0, 0, 0];
2888
2946
  for (let i = 0; i < nodes.length; i++) {
2889
- const element = `nodes[${i}]`;
2890
- const record = nodes[i];
2891
- if (!isJsonObject(record) || !isJsonObject(record.data)) {
2892
- ctx.badElement("node", element, "an element with a data object");
2893
- continue;
2947
+ readCytoscapeNode(ctx, reading, nodes[i], `nodes[${i}]`);
2948
+ }
2949
+ resolveCytoscapeParents(ctx, reading.parents, parentColumn);
2950
+ throwIfAborted(ctx.options.signal);
2951
+ importCytoscapeEdges(ctx, edges, edgeClassesColumn);
2952
+ ctx.setMeta({ dialect: "cytoscape", cytoscape: extra }, ctx.weightOriginPatch());
2953
+ }
2954
+ function cytoscapeRoot(ctx, root) {
2955
+ if (Array.isArray(root)) {
2956
+ return { elements: root };
2957
+ }
2958
+ if (!isJsonObject(root)) {
2959
+ ctx.report.fail(
2960
+ JSON_ISSUE.SHAPE,
2961
+ `a Cytoscape document must be an object or an array, found ${describe(root)}`
2962
+ );
2963
+ }
2964
+ ctx.writeGraphDict(root.data, "data");
2965
+ const rest = {};
2966
+ for (const key of Object.keys(root)) {
2967
+ if (key !== "elements" && key !== "data") {
2968
+ rest[key] = root[key];
2894
2969
  }
2895
- const { data } = record;
2896
- const id = ctx.coerceId(hasKey(data, "id") ? data.id : void 0, element);
2897
- if (id === null) {
2898
- ctx.countSkipped("node");
2970
+ }
2971
+ return Object.keys(rest).length > 0 ? { elements: root.elements, extra: rest } : { elements: root.elements };
2972
+ }
2973
+ function readCytoscapeNode(ctx, reading, record, element) {
2974
+ const { report } = ctx;
2975
+ if (!isJsonObject(record) || !isJsonObject(record.data)) {
2976
+ ctx.badElement("node", element, "an element with a data object");
2977
+ return;
2978
+ }
2979
+ const { data } = record;
2980
+ const id = ctx.coerceId(hasKey(data, "id") ? data.id : void 0, element);
2981
+ if (id === null) {
2982
+ ctx.countSkipped("node");
2983
+ return;
2984
+ }
2985
+ const index = ctx.pushNode(id, element);
2986
+ if (index < 0) {
2987
+ return;
2988
+ }
2989
+ if (present(data, "source") && present(data, "target")) {
2990
+ report.warning(
2991
+ "validation-error",
2992
+ JSON_ISSUE.INCONSISTENT,
2993
+ `${element} has data.source and data.target, the shape of an edge, but its section or group says node; read as a node`,
2994
+ { element }
2995
+ );
2996
+ }
2997
+ try {
2998
+ writeCytoscapeData(ctx, reading, index, data, element);
2999
+ writeCytoscapePosition$1(ctx, reading, index, record.position, element);
3000
+ writeClasses(ctx, ctx.nodes, reading.classesColumn, index, record.classes, element);
3001
+ writeElementKeys(ctx.nodes, index, record, element);
3002
+ } catch (err) {
3003
+ report.recordError(err, { element: String(id) });
3004
+ }
3005
+ }
3006
+ function writeCytoscapeData(ctx, reading, index, data, element) {
3007
+ for (const key of Object.keys(data)) {
3008
+ if (key === "id") {
2899
3009
  continue;
2900
3010
  }
2901
- const index = ctx.pushNode(id, element);
2902
- if (index < 0) {
3011
+ if (key !== "parent") {
3012
+ ctx.nodes.write(index, key, data[key], SUFFIX.data, element);
2903
3013
  continue;
2904
3014
  }
2905
- if (present(data, "source") && present(data, "target")) {
2906
- report.warning(
2907
- "validation-error",
2908
- JSON_ISSUE.INCONSISTENT,
2909
- `${element} has data.source and data.target, the shape of an edge, but its section or group says node; read as a node`,
2910
- { element }
2911
- );
3015
+ const raw = data.parent;
3016
+ if (raw === void 0 || raw === null) {
3017
+ continue;
2912
3018
  }
2913
- try {
2914
- for (const key of Object.keys(data)) {
2915
- if (key === "id") {
2916
- continue;
2917
- }
2918
- if (key === "parent") {
2919
- const raw = data.parent;
2920
- if (raw !== void 0 && raw !== null) {
2921
- const parent = ctx.coerceId(raw, `${element}.data.parent`);
2922
- if (parent !== null) {
2923
- parents.push({ index, parent, element });
2924
- }
2925
- }
2926
- continue;
2927
- }
2928
- ctx.nodes.write(index, key, data[key], SUFFIX.data, element);
2929
- }
2930
- const { position } = record;
2931
- if (position !== void 0 && position !== null) {
2932
- const z = isJsonObject(position) ? position.z ?? 0 : 0;
2933
- if (isJsonObject(position) && isCoordinate(position.x) && isCoordinate(position.y) && isCoordinate(z)) {
2934
- point[0] = position.x;
2935
- point[1] = flipY(position.y);
2936
- point[2] = z;
2937
- ctx.nodes.set(positionColumn, index, point);
2938
- } else {
2939
- report.error(
2940
- "validation-error",
2941
- JSON_ISSUE.BAD_VALUE,
2942
- `${element}: position must be an object with numeric x and y (and z) that are finite numbers`,
2943
- { element }
2944
- );
2945
- }
2946
- }
2947
- writeClasses(ctx, ctx.nodes, classesColumn, index, record.classes, element);
2948
- writeElementKeys(ctx.nodes, index, record, element);
2949
- } catch (err) {
2950
- report.recordError(err, { element: String(id) });
3019
+ const parent = ctx.coerceId(raw, `${element}.data.parent`);
3020
+ if (parent !== null) {
3021
+ reading.parents.push({ index, parent, element });
2951
3022
  }
2952
3023
  }
2953
- resolveCytoscapeParents(ctx, parents, parentColumn);
2954
- throwIfAborted(ctx.options.signal);
2955
- importCytoscapeEdges(ctx, edges, edgeClassesColumn);
2956
- ctx.setMeta({ dialect: "cytoscape", cytoscape: extra }, ctx.weightOriginPatch());
3024
+ }
3025
+ function writeCytoscapePosition$1(ctx, reading, index, position, element) {
3026
+ if (position === void 0 || position === null) {
3027
+ return;
3028
+ }
3029
+ const z = isJsonObject(position) ? position.z ?? 0 : 0;
3030
+ if (isJsonObject(position) && isCoordinate(position.x) && isCoordinate(position.y) && isCoordinate(z)) {
3031
+ const { point } = reading;
3032
+ point[0] = position.x;
3033
+ point[1] = flipY(position.y);
3034
+ point[2] = z;
3035
+ ctx.nodes.set(reading.positionColumn, index, point);
3036
+ } else {
3037
+ ctx.report.error(
3038
+ "validation-error",
3039
+ JSON_ISSUE.BAD_VALUE,
3040
+ `${element}: position must be an object with numeric x and y (and z) that are finite numbers`,
3041
+ { element }
3042
+ );
3043
+ }
2957
3044
  }
2958
3045
  function resolveCytoscapeParents(ctx, parents, parentColumn) {
2959
3046
  const { report } = ctx;
@@ -3028,27 +3115,31 @@ function importCytoscapeEdges(ctx, edges, edgeClassesColumn) {
3028
3115
  ctx.missingEndpoint(element, `data.${present(data, "source") ? "target" : "source"}`);
3029
3116
  continue;
3030
3117
  }
3031
- try {
3032
- const u = ctx.coerceId(data.source, `${element}.data.source`);
3033
- const v = ctx.coerceId(data.target, `${element}.data.target`);
3034
- if (u === null || v === null) {
3035
- ctx.countSkipped("edge");
3036
- continue;
3037
- }
3038
- const idValue = ctx.edgeIdValue(ids, data.id);
3039
- const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(data), element);
3040
- ctx.setEdgeId(ids, edge, idValue);
3041
- const { weightFrom } = ctx.options;
3042
- for (const key of Object.keys(data)) {
3043
- if (key !== "id" && key !== "source" && key !== "target" && key !== weightFrom) {
3044
- ctx.edges.write(edge, key, data[key], SUFFIX.data, element);
3045
- }
3118
+ importCytoscapeEdge(ctx, { ids, kind, edgeClassesColumn }, record, data, element);
3119
+ }
3120
+ }
3121
+ function importCytoscapeEdge(ctx, shared, record, data, element) {
3122
+ const { ids, kind, edgeClassesColumn } = shared;
3123
+ try {
3124
+ const u = ctx.coerceId(data.source, `${element}.data.source`);
3125
+ const v = ctx.coerceId(data.target, `${element}.data.target`);
3126
+ if (u === null || v === null) {
3127
+ ctx.countSkipped("edge");
3128
+ return;
3129
+ }
3130
+ const idValue = ctx.edgeIdValue(ids, data.id);
3131
+ const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(data), element);
3132
+ ctx.setEdgeId(ids, edge, idValue);
3133
+ const { weightFrom } = ctx.options;
3134
+ for (const key of Object.keys(data)) {
3135
+ if (key !== "id" && key !== "source" && key !== "target" && key !== weightFrom) {
3136
+ ctx.edges.write(edge, key, data[key], SUFFIX.data, element);
3046
3137
  }
3047
- writeClasses(ctx, ctx.edges, edgeClassesColumn, edge, record.classes, element);
3048
- writeElementKeys(ctx.edges, edge, record, element);
3049
- } catch (err) {
3050
- ctx.skip(err, "edge", element);
3051
3138
  }
3139
+ writeClasses(ctx, ctx.edges, edgeClassesColumn, edge, record.classes, element);
3140
+ writeElementKeys(ctx.edges, edge, record, element);
3141
+ } catch (err) {
3142
+ ctx.skip(err, "edge", element);
3052
3143
  }
3053
3144
  }
3054
3145
  function cytoscapeSections(ctx, elements) {
@@ -3566,21 +3657,7 @@ function writeNode(ctx, columns, vocabulary, record, row, element) {
3566
3657
  }
3567
3658
  function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
3568
3659
  const path = `${element}.meta`;
3569
- const { definition } = meta;
3570
- if (isJsonObject(definition)) {
3571
- const xrefs2 = strings$1(ctx, definition.xrefs, `${path}.definition.xrefs`);
3572
- if (typeof definition.val === "string") {
3573
- columns.node("def", row, definition.val);
3574
- columns.node("def.xrefs", row, xrefs2);
3575
- } else {
3576
- badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
3577
- }
3578
- if (definition.meta !== void 0) {
3579
- unrecognized["meta.definition.meta"] = definition.meta;
3580
- }
3581
- } else if (definition !== void 0 && definition !== null) {
3582
- badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
3583
- }
3660
+ writeDefinition(ctx, columns, meta.definition, row, unrecognized, path);
3584
3661
  const comments = strings$1(ctx, meta.comments, `${path}.comments`);
3585
3662
  if (comments.length > 0) {
3586
3663
  columns.node("comment", row, comments.join("\n"));
@@ -3609,6 +3686,22 @@ function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
3609
3686
  }
3610
3687
  }
3611
3688
  }
3689
+ function writeDefinition(ctx, columns, definition, row, unrecognized, path) {
3690
+ if (isJsonObject(definition)) {
3691
+ const xrefs = strings$1(ctx, definition.xrefs, `${path}.definition.xrefs`);
3692
+ if (typeof definition.val === "string") {
3693
+ columns.node("def", row, definition.val);
3694
+ columns.node("def.xrefs", row, xrefs);
3695
+ } else {
3696
+ badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
3697
+ }
3698
+ if (definition.meta !== void 0) {
3699
+ unrecognized["meta.definition.meta"] = definition.meta;
3700
+ }
3701
+ } else if (definition !== void 0 && definition !== null) {
3702
+ badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
3703
+ }
3704
+ }
3612
3705
  function synonymsOf(ctx, vocabulary, value, path) {
3613
3706
  if (value === void 0 || value === null) {
3614
3707
  return [];
@@ -5782,7 +5875,6 @@ function* writeCytoscape(snapshot, p) {
5782
5875
  const c = { w: new JsonWriter(resolved.indent), ids: snapshot.ids, nonfinite: { count: 0 } };
5783
5876
  const { w } = c;
5784
5877
  const parentSlots = /* @__PURE__ */ new Set(["parent"]);
5785
- const positionSlots = /* @__PURE__ */ new Set(["cytoscapePosition"]);
5786
5878
  w.open("{");
5787
5879
  w.key("elements");
5788
5880
  w.open("{");
@@ -5798,17 +5890,7 @@ function* writeCytoscape(snapshot, p) {
5798
5890
  writeSlots(c, p.nodes, i, parentSlots);
5799
5891
  writeSlots(c, p.nodes, i, ATTRIBUTE_SLOTS);
5800
5892
  w.close("}");
5801
- for (const item of p.nodes) {
5802
- if (positionSlots.has(item.slot) && item.column.isSet(i)) {
5803
- const value = item.column.value(i);
5804
- const f32 = item.column.dtype === "f32";
5805
- w.key("position");
5806
- w.open("{");
5807
- w.member("x", numberText(value[0], f32, c.nonfinite));
5808
- w.member("y", numberText(flipY(value[1]), f32, c.nonfinite));
5809
- w.close("}");
5810
- }
5811
- }
5893
+ writeCytoscapePosition(c, p.nodes, i);
5812
5894
  writeSlots(c, p.nodes, i, ELEMENT_SLOTS);
5813
5895
  w.close("}");
5814
5896
  yield w.take();
@@ -5845,17 +5927,34 @@ function* writeCytoscape(snapshot, p) {
5845
5927
  w.key("data");
5846
5928
  writeGraphObject(c, p);
5847
5929
  }
5848
- const extra = resolved.shape.cytoscape;
5849
- if (extra !== void 0) {
5850
- for (const key of Object.keys(extra)) {
5851
- if (key !== "elements" && key !== "data") {
5852
- w.member(key, valueText(extra[key], false, c.nonfinite));
5853
- }
5854
- }
5855
- }
5930
+ writeCytoscapeExtra(c, resolved.shape.cytoscape);
5856
5931
  w.close("}");
5857
5932
  yield w.take();
5858
5933
  }
5934
+ function writeCytoscapePosition(c, items, i) {
5935
+ const { w } = c;
5936
+ for (const item of items) {
5937
+ if (item.slot === "cytoscapePosition" && item.column.isSet(i)) {
5938
+ const value = item.column.value(i);
5939
+ const f32 = item.column.dtype === "f32";
5940
+ w.key("position");
5941
+ w.open("{");
5942
+ w.member("x", numberText(value[0], f32, c.nonfinite));
5943
+ w.member("y", numberText(flipY(value[1]), f32, c.nonfinite));
5944
+ w.close("}");
5945
+ }
5946
+ }
5947
+ }
5948
+ function writeCytoscapeExtra(c, extra) {
5949
+ if (extra === void 0) {
5950
+ return;
5951
+ }
5952
+ for (const key of Object.keys(extra)) {
5953
+ if (key !== "elements" && key !== "data") {
5954
+ c.w.member(key, valueText(extra[key], false, c.nonfinite));
5955
+ }
5956
+ }
5957
+ }
5859
5958
  function edgeIdGenerator(snapshot, p) {
5860
5959
  const used = /* @__PURE__ */ new Set();
5861
5960
  for (let i = 0; i < snapshot.nodeCount; i++) {
@@ -5946,4 +6045,4 @@ export {
5946
6045
  rankFormats as r,
5947
6046
  sniffFormat as s
5948
6047
  };
5949
- //# sourceMappingURL=exporter-Bcp-l4Bo.js.map
6048
+ //# sourceMappingURL=exporter-CpRyHZ3H.js.map