@graphty/graph-io 0.3.39 → 0.3.41

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 (213) hide show
  1. package/dist/chunks/{choose-CS3fvGT1.js → choose-CwFQamH9.js} +2 -2
  2. package/dist/chunks/{choose-CS3fvGT1.js.map → choose-CwFQamH9.js.map} +1 -1
  3. package/dist/chunks/{constants-DqKZT6cH.js → constants-Cf4Nn6tw.js} +2 -2
  4. package/dist/chunks/{constants-DqKZT6cH.js.map → constants-Cf4Nn6tw.js.map} +1 -1
  5. package/dist/chunks/{escape-BpYMQZVa.js → escape-DBb8zuNE.js} +4 -3
  6. package/dist/chunks/escape-DBb8zuNE.js.map +1 -0
  7. package/dist/chunks/{export-B-aVCwyG.js → export-DD3Lvw-F.js} +173 -116
  8. package/dist/chunks/export-DD3Lvw-F.js.map +1 -0
  9. package/dist/chunks/{exporter-CNJZF_BN.js → exporter-BqtmlxNr.js} +545 -459
  10. package/dist/chunks/exporter-BqtmlxNr.js.map +1 -0
  11. package/dist/chunks/{exporter-BqKs1Q12.js → exporter-CS35R6Fg.js} +6 -5
  12. package/dist/chunks/exporter-CS35R6Fg.js.map +1 -0
  13. package/dist/chunks/{exporter-DXqCPNrI.js → exporter-D8r1N2dU.js} +67 -42
  14. package/dist/chunks/exporter-D8r1N2dU.js.map +1 -0
  15. package/dist/chunks/{exporter-SFYkDzD0.js → exporter-NMplSnYn.js} +23 -20
  16. package/dist/chunks/{exporter-SFYkDzD0.js.map → exporter-NMplSnYn.js.map} +1 -1
  17. package/dist/chunks/{importer-CSt-gaYE.js → importer-BKC7AmCA.js} +42 -29
  18. package/dist/chunks/importer-BKC7AmCA.js.map +1 -0
  19. package/dist/chunks/{importer-DvFznt5-.js → importer-BdWHmlmG.js} +112 -62
  20. package/dist/chunks/importer-BdWHmlmG.js.map +1 -0
  21. package/dist/chunks/{importer-CqgYq4Ld.js → importer-BfbzWk6k.js} +202 -181
  22. package/dist/chunks/importer-BfbzWk6k.js.map +1 -0
  23. package/dist/chunks/{importer-PVXkeoaS.js → importer-BmaZcskq.js} +79 -66
  24. package/dist/chunks/importer-BmaZcskq.js.map +1 -0
  25. package/dist/chunks/{importer-B7Ir269L.js → importer-DviEsHy4.js} +118 -72
  26. package/dist/chunks/importer-DviEsHy4.js.map +1 -0
  27. package/dist/chunks/{importer--tQQsY4W.js → importer-S-abxJHn.js} +5 -5
  28. package/dist/chunks/{importer--tQQsY4W.js.map → importer-S-abxJHn.js.map} +1 -1
  29. package/dist/chunks/{importer-BfJ1jnNr.js → importer-r29cWnEf.js} +28 -13
  30. package/dist/chunks/importer-r29cWnEf.js.map +1 -0
  31. package/dist/chunks/{json-elements-CXs4z1iL.js → json-elements-DdF-etPT.js} +7 -5
  32. package/dist/chunks/{json-elements-CXs4z1iL.js.map → json-elements-DdF-etPT.js.map} +1 -1
  33. package/dist/chunks/{ontology-export-50L9DOV4.js → ontology-export-BC0zyPhj.js} +2 -2
  34. package/dist/chunks/{ontology-export-50L9DOV4.js.map → ontology-export-BC0zyPhj.js.map} +1 -1
  35. package/dist/chunks/{records-C9jd7yLD.js → records-Uc3LkABx.js} +150 -106
  36. package/dist/chunks/records-Uc3LkABx.js.map +1 -0
  37. package/dist/chunks/{text-Bjfa1xYL.js → text-Bh9SaAob.js} +20 -11
  38. package/dist/chunks/text-Bh9SaAob.js.map +1 -0
  39. package/dist/csv.js +67 -49
  40. package/dist/csv.js.map +1 -1
  41. package/dist/cx.js +1 -1
  42. package/dist/cx2.js +2 -2
  43. package/dist/cys.js +1 -1
  44. package/dist/dot.js +1 -1
  45. package/dist/gexf.js +199 -99
  46. package/dist/gexf.js.map +1 -1
  47. package/dist/gml.js +170 -149
  48. package/dist/gml.js.map +1 -1
  49. package/dist/graph-io.js +26 -26
  50. package/dist/graphml.js +2 -2
  51. package/dist/json.js +1 -1
  52. package/dist/neo4j.js +103 -65
  53. package/dist/neo4j.js.map +1 -1
  54. package/dist/obo.js +1 -1
  55. package/dist/pajek.js +1 -1
  56. package/dist/src/common/attributes.d.ts.map +1 -1
  57. package/dist/src/common/attributes.js +34 -9
  58. package/dist/src/common/attributes.js.map +1 -1
  59. package/dist/src/common/input.d.ts.map +1 -1
  60. package/dist/src/common/input.js +180 -102
  61. package/dist/src/common/input.js.map +1 -1
  62. package/dist/src/common/json-elements.d.ts.map +1 -1
  63. package/dist/src/common/json-elements.js +4 -2
  64. package/dist/src/common/json-elements.js.map +1 -1
  65. package/dist/src/common/text.d.ts +7 -0
  66. package/dist/src/common/text.d.ts.map +1 -1
  67. package/dist/src/common/text.js +15 -7
  68. package/dist/src/common/text.js.map +1 -1
  69. package/dist/src/common/xml.d.ts.map +1 -1
  70. package/dist/src/common/xml.js +2 -1
  71. package/dist/src/common/xml.js.map +1 -1
  72. package/dist/src/common/zip.d.ts.map +1 -1
  73. package/dist/src/common/zip.js +36 -19
  74. package/dist/src/common/zip.js.map +1 -1
  75. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  76. package/dist/src/formats/csv/exporter.js +77 -25
  77. package/dist/src/formats/csv/exporter.js.map +1 -1
  78. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  79. package/dist/src/formats/csv/importer.js +16 -6
  80. package/dist/src/formats/csv/importer.js.map +1 -1
  81. package/dist/src/formats/csv/records.d.ts.map +1 -1
  82. package/dist/src/formats/csv/records.js +156 -110
  83. package/dist/src/formats/csv/records.js.map +1 -1
  84. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  85. package/dist/src/formats/cx/importer.js +108 -53
  86. package/dist/src/formats/cx/importer.js.map +1 -1
  87. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  88. package/dist/src/formats/cx2/exporter.js +2 -1
  89. package/dist/src/formats/cx2/exporter.js.map +1 -1
  90. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  91. package/dist/src/formats/cx2/importer.js +28 -6
  92. package/dist/src/formats/cx2/importer.js.map +1 -1
  93. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  94. package/dist/src/formats/cys/tables.js +11 -8
  95. package/dist/src/formats/cys/tables.js.map +1 -1
  96. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  97. package/dist/src/formats/gexf/exporter.js +69 -39
  98. package/dist/src/formats/gexf/exporter.js.map +1 -1
  99. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  100. package/dist/src/formats/gexf/importer.js +138 -50
  101. package/dist/src/formats/gexf/importer.js.map +1 -1
  102. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  103. package/dist/src/formats/gml/exporter.js +51 -35
  104. package/dist/src/formats/gml/exporter.js.map +1 -1
  105. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  106. package/dist/src/formats/gml/importer.js +103 -58
  107. package/dist/src/formats/gml/importer.js.map +1 -1
  108. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  109. package/dist/src/formats/gml/syntax.js +17 -8
  110. package/dist/src/formats/gml/syntax.js.map +1 -1
  111. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  112. package/dist/src/formats/graphml/exporter.js +36 -25
  113. package/dist/src/formats/graphml/exporter.js.map +1 -1
  114. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  115. package/dist/src/formats/graphml/importer.js +20 -15
  116. package/dist/src/formats/graphml/importer.js.map +1 -1
  117. package/dist/src/formats/graphml/tree.js +23 -14
  118. package/dist/src/formats/graphml/tree.js.map +1 -1
  119. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  120. package/dist/src/formats/graphml/yfiles.js +22 -10
  121. package/dist/src/formats/graphml/yfiles.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 +13 -0
  152. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  153. package/dist/src/formats/xgmml/emit.js +112 -50
  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 +92 -34
  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/common/attributes.ts +59 -19
  166. package/src/common/input.ts +216 -102
  167. package/src/common/json-elements.ts +4 -2
  168. package/src/common/text.ts +24 -15
  169. package/src/common/xml.ts +2 -1
  170. package/src/common/zip.ts +47 -18
  171. package/src/formats/csv/exporter.ts +103 -39
  172. package/src/formats/csv/importer.ts +17 -6
  173. package/src/formats/csv/records.ts +162 -109
  174. package/src/formats/cx/importer.ts +140 -58
  175. package/src/formats/cx2/exporter.ts +2 -1
  176. package/src/formats/cx2/importer.ts +34 -10
  177. package/src/formats/cys/tables.ts +11 -10
  178. package/src/formats/gexf/exporter.ts +71 -38
  179. package/src/formats/gexf/importer.ts +173 -63
  180. package/src/formats/gml/exporter.ts +78 -82
  181. package/src/formats/gml/importer.ts +119 -68
  182. package/src/formats/gml/syntax.ts +18 -8
  183. package/src/formats/graphml/exporter.ts +46 -27
  184. package/src/formats/graphml/importer.ts +21 -13
  185. package/src/formats/graphml/tree.ts +22 -12
  186. package/src/formats/graphml/yfiles.ts +23 -10
  187. package/src/formats/json/exporter.ts +40 -21
  188. package/src/formats/json/importer.ts +701 -385
  189. package/src/formats/json/obographs.ts +35 -15
  190. package/src/formats/neo4j/exporter.ts +79 -41
  191. package/src/formats/neo4j/header.ts +50 -16
  192. package/src/formats/neo4j/importer.ts +21 -10
  193. package/src/formats/obo/exporter.ts +34 -17
  194. package/src/formats/pajek/exporter.ts +180 -117
  195. package/src/formats/pajek/importer.ts +27 -15
  196. package/src/formats/pajek/syntax.ts +99 -58
  197. package/src/formats/xgmml/emit.ts +122 -50
  198. package/src/formats/xgmml/exporter.ts +103 -35
  199. package/src/formats/xgmml/importer.ts +45 -23
  200. package/src/sniff.ts +115 -59
  201. package/dist/chunks/escape-BpYMQZVa.js.map +0 -1
  202. package/dist/chunks/export-B-aVCwyG.js.map +0 -1
  203. package/dist/chunks/exporter-BqKs1Q12.js.map +0 -1
  204. package/dist/chunks/exporter-CNJZF_BN.js.map +0 -1
  205. package/dist/chunks/exporter-DXqCPNrI.js.map +0 -1
  206. package/dist/chunks/importer-B7Ir269L.js.map +0 -1
  207. package/dist/chunks/importer-BfJ1jnNr.js.map +0 -1
  208. package/dist/chunks/importer-CSt-gaYE.js.map +0 -1
  209. package/dist/chunks/importer-CqgYq4Ld.js.map +0 -1
  210. package/dist/chunks/importer-DvFznt5-.js.map +0 -1
  211. package/dist/chunks/importer-PVXkeoaS.js.map +0 -1
  212. package/dist/chunks/records-C9jd7yLD.js.map +0 -1
  213. 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-CXs4z1iL.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-DD3Lvw-F.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-DdF-etPT.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-Bh9SaAob.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-BC0zyPhj.js";
7
7
  const JSON_DIALECTS = Object.freeze([
8
8
  "node-link",
9
9
  "d3",
@@ -373,38 +373,42 @@ function skeletonOf(text) {
373
373
  }
374
374
  const root = {};
375
375
  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
- }
376
+ root[key] = placeholderOf(key, keys);
405
377
  }
406
378
  return root;
407
379
  }
380
+ function placeholderOf(key, keys) {
381
+ switch (key) {
382
+ case "graph":
383
+ case "options":
384
+ return objectOf(keys.get(key));
385
+ case "graphs":
386
+ return graphsPlaceholder(keys);
387
+ case "nodes":
388
+ case "edges":
389
+ case "links": {
390
+ const first = keys.get(`${key}[0]`);
391
+ return first === void 0 ? [] : [objectOf(first)];
392
+ }
393
+ default:
394
+ return true;
395
+ }
396
+ }
397
+ function graphsPlaceholder(keys) {
398
+ const nodes = keys.get("graphs[0].nodes[]");
399
+ const edges = keys.get("graphs[0].edges[]");
400
+ if (nodes === void 0 && edges === void 0) {
401
+ return [];
402
+ }
403
+ const graph = {};
404
+ if (nodes !== void 0) {
405
+ graph.nodes = [objectOf(nodes)];
406
+ }
407
+ if (edges !== void 0) {
408
+ graph.edges = [objectOf(edges)];
409
+ }
410
+ return [graph];
411
+ }
408
412
  function objectOf(names) {
409
413
  const out = {};
410
414
  if (names !== void 0) {
@@ -421,28 +425,6 @@ function scanKeys(text) {
421
425
  const counts = [];
422
426
  let pendingKey = null;
423
427
  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
428
  let i = 0;
447
429
  const n = text.length;
448
430
  while (i < n) {
@@ -478,7 +460,7 @@ function scanKeys(text) {
478
460
  pendingKey = null;
479
461
  } else if (ch === ":") {
480
462
  if (pendingKey !== null) {
481
- const path = pathOf();
463
+ const path = keyPathOf(kinds, labels);
482
464
  if (path !== null) {
483
465
  let set = found.get(path);
484
466
  if (set === void 0) {
@@ -500,6 +482,45 @@ function scanKeys(text) {
500
482
  }
501
483
  return found;
502
484
  }
485
+ function keyPathOf(kinds, labels) {
486
+ switch (kinds.length) {
487
+ case 1:
488
+ return kinds[0] === "object" ? "" : null;
489
+ case 2:
490
+ return nestedObjectPath(kinds, labels);
491
+ case 3:
492
+ return sectionElementPath(kinds, labels);
493
+ case 5:
494
+ return graphsMemberPath(kinds, labels);
495
+ default:
496
+ return null;
497
+ }
498
+ }
499
+ function nestedObjectPath(kinds, labels) {
500
+ if (kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
501
+ return "nodes[0]";
502
+ }
503
+ if (kinds[0] === "object" && kinds[1] === "object") {
504
+ return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
505
+ }
506
+ return null;
507
+ }
508
+ function sectionElementPath(kinds, labels) {
509
+ if (kinds[0] !== "object" || kinds[1] !== "array" || kinds[2] !== "object" || labels[2] !== "0") {
510
+ return null;
511
+ }
512
+ const section = labels[1];
513
+ return section === "nodes" || section === "edges" || section === "links" ? `${section}[0]` : null;
514
+ }
515
+ function graphsMemberPath(kinds, labels) {
516
+ if (kinds.join() !== "object,array,object,array,object" || labels[1] !== "graphs" || labels[2] !== "0") {
517
+ return null;
518
+ }
519
+ if (labels[3] === "nodes") {
520
+ return "graphs[0].nodes[]";
521
+ }
522
+ return labels[3] === "edges" ? "graphs[0].edges[]" : null;
523
+ }
503
524
  function scanString(text, from) {
504
525
  let i = from;
505
526
  while (i < text.length) {
@@ -2076,18 +2097,7 @@ function importAdjacency(ctx, root) {
2076
2097
  const multigraph = hasKey(root, "multigraph") ? flagOf(root.multigraph, "multigraph", false, report) : null;
2077
2098
  ctx.setHeader(directed);
2078
2099
  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
- }
2100
+ reportUnreadAdjacencyKeys(ctx, root);
2091
2101
  const lists = adjacency ?? [];
2092
2102
  ctx.sink.reserve(
2093
2103
  nodes.length,
@@ -2095,90 +2105,120 @@ function importAdjacency(ctx, root) {
2095
2105
  );
2096
2106
  const idKey = ctx.json.nodeIdKey ?? "id";
2097
2107
  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
- }
2108
+ const owners = nodes.map((record, i) => pushAdjacencyNode(ctx, record, `nodes[${i}]`, idKey));
2119
2109
  throwIfAborted(ctx.options.signal);
2120
- const kind = ctx.uniformKind();
2121
- const { weightFrom } = ctx.options;
2122
- const pending = /* @__PURE__ */ new Map();
2123
- let disagreeing = 0;
2110
+ const reading = {
2111
+ owners,
2112
+ nodeCount: nodes.length,
2113
+ directed,
2114
+ kind: ctx.uniformKind(),
2115
+ idKey,
2116
+ // undirected: entries read once whose mirror is still to come, by pair and key, with their attributes
2117
+ pending: /* @__PURE__ */ new Map(),
2118
+ disagreeing: 0
2119
+ };
2124
2120
  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`,
2121
+ readAdjacencyList(ctx, reading, i, lists[i]);
2122
+ }
2123
+ reportAdjacencyShape(
2124
+ ctx,
2125
+ nodes.length,
2126
+ adjacency === null ? null : lists.length,
2127
+ reading.disagreeing,
2128
+ reading.pending
2129
+ );
2130
+ ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
2131
+ }
2132
+ const ADJACENCY_DOCUMENT_KEYS = /* @__PURE__ */ new Set(["nodes", "adjacency", "directed", "multigraph", "graph"]);
2133
+ function reportUnreadAdjacencyKeys(ctx, root) {
2134
+ for (const key of Object.keys(root)) {
2135
+ if (!ADJACENCY_DOCUMENT_KEYS.has(key)) {
2136
+ ctx.report.warning(
2137
+ "unsupported",
2138
+ JSON_ISSUE.UNREAD_KEY,
2139
+ `top-level key ${key} (${describe(root[key])}) is not read; dropped`,
2138
2140
  {
2139
- element
2141
+ element: key
2140
2142
  }
2141
2143
  );
2142
- report.counts.skippedEdges += list.length;
2143
- continue;
2144
2144
  }
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;
2145
+ }
2146
+ }
2147
+ function pushAdjacencyNode(ctx, record, element, idKey) {
2148
+ if (!isJsonObject(record)) {
2149
+ ctx.badElement("node", element);
2150
+ return null;
2151
+ }
2152
+ const id = ctx.coerceId(hasKey(record, idKey) ? record[idKey] : void 0, element);
2153
+ if (id === null) {
2154
+ ctx.countSkipped("node");
2155
+ return null;
2156
+ }
2157
+ const index = ctx.pushNode(id, element);
2158
+ if (index < 0) {
2159
+ return null;
2160
+ }
2161
+ writeFlat(ctx.nodes, index, record, id, (key) => key !== idKey);
2162
+ return id;
2163
+ }
2164
+ function readAdjacencyList(ctx, reading, i, list) {
2165
+ const { report } = ctx;
2166
+ const element = `adjacency[${i}]`;
2167
+ if (!Array.isArray(list)) {
2168
+ report.error("validation-error", JSON_ISSUE.BAD_ELEMENT, `${element} is not an array`, { element });
2169
+ return;
2170
+ }
2171
+ const source = i < reading.owners.length ? reading.owners[i] : null;
2172
+ if (source === null) {
2173
+ const why = i < reading.nodeCount ? `nodes[${i}] was skipped` : `there is no nodes[${i}]`;
2174
+ report.error(
2175
+ "missing-value",
2176
+ JSON_ISSUE.BAD_INDEX,
2177
+ `${element}: ${why}; its ${list.length} edge${plural(list.length)} ${agree(list.length, "is", "are")} skipped`,
2178
+ {
2179
+ element
2151
2180
  }
2152
- if (!hasKey(record, idKey)) {
2153
- ctx.missingEndpoint(entry, idKey);
2154
- continue;
2181
+ );
2182
+ report.counts.skippedEdges += list.length;
2183
+ return;
2184
+ }
2185
+ for (let j = 0; j < list.length; j++) {
2186
+ readAdjacencyEntry(ctx, reading, source, list[j], element, `${element}[${j}]`);
2187
+ }
2188
+ }
2189
+ function readAdjacencyEntry(ctx, reading, source, record, element, entry) {
2190
+ const { idKey } = reading;
2191
+ if (!isJsonObject(record)) {
2192
+ ctx.badElement("edge", entry);
2193
+ return;
2194
+ }
2195
+ if (!hasKey(record, idKey)) {
2196
+ ctx.missingEndpoint(entry, idKey);
2197
+ return;
2198
+ }
2199
+ try {
2200
+ const target = ctx.coerceId(record[idKey], `${entry}.${idKey}`);
2201
+ if (target === null) {
2202
+ ctx.countSkipped("edge");
2203
+ return;
2204
+ }
2205
+ if (!reading.directed) {
2206
+ const mirror = mirroredEntry(reading.pending, source, target, record, idKey);
2207
+ reading.disagreeing += mirror === "disagrees" ? 1 : 0;
2208
+ if (mirror !== "new") {
2209
+ return;
2155
2210
  }
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);
2211
+ }
2212
+ const edge = ctx.pushEdge(source, target, reading.kind, ctx.weightOf(record), entry);
2213
+ const { weightFrom } = ctx.options;
2214
+ for (const key of Object.keys(record)) {
2215
+ if (key !== idKey && key !== weightFrom) {
2216
+ ctx.edges.write(edge, key, record[key], SUFFIX.data, element);
2177
2217
  }
2178
2218
  }
2219
+ } catch (err) {
2220
+ ctx.skip(err, "edge", entry);
2179
2221
  }
2180
- reportAdjacencyShape(ctx, nodes.length, adjacency === null ? null : lists.length, disagreeing, pending);
2181
- ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
2182
2222
  }
2183
2223
  function reportAdjacencyShape(ctx, nodes, lists, disagreeing, pending) {
2184
2224
  const { report } = ctx;
@@ -2298,107 +2338,120 @@ function importGraphology(ctx, root) {
2298
2338
  element: "options"
2299
2339
  });
2300
2340
  }
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);
2341
+ const type = graphologyType(ctx, options);
2342
+ ctx.setHeader(graphologyDirected(ctx, type, edges));
2324
2343
  const multi = hasKey(options, "multi") ? flagOf(options.multi, "options.multi", false, report) : null;
2325
2344
  const allowSelfLoops = hasKey(options, "allowSelfLoops") ? flagOf(options.allowSelfLoops, "options.allowSelfLoops", true, report) : void 0;
2326
2345
  ctx.writeGraphDict(root.attributes, "attributes");
2327
2346
  ctx.reportNodeIdFrom("graphology", "the node key");
2328
2347
  ctx.sink.reserve(nodes.length, edges.length);
2329
2348
  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);
2349
+ pushGraphologyNode(ctx, nodes[i], `nodes[${i}]`);
2342
2350
  }
2343
2351
  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;
2352
+ const reading = {
2353
+ ids: ctx.declareEdgeIds(edges, (edge) => edge.key, "key", true),
2354
+ type,
2355
+ allowSelfLoops,
2356
+ // what the edges do against the declared options: graphology itself refuses such a document
2357
+ violations: { selfLoops: 0, parallels: 0, flags: 0 },
2358
+ pairs: multi === false ? /* @__PURE__ */ new Set() : null
2359
+ };
2347
2360
  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;
2361
+ readGraphologyEdge(ctx, reading, edges[i], `edges[${i}]`);
2362
+ }
2363
+ reportGraphologyViolations(ctx, reading.violations, type);
2364
+ ctx.setMeta({ dialect: "graphology", allowSelfLoops }, { declaredMultigraph: multi, ...ctx.weightOriginPatch() });
2365
+ }
2366
+ function graphologyType(ctx, options) {
2367
+ if (options.type === "directed" || options.type === "undirected" || options.type === "mixed") {
2368
+ return options.type;
2369
+ }
2370
+ if (options.type !== void 0 && options.type !== null) {
2371
+ ctx.report.warning(
2372
+ "validation-error",
2373
+ JSON_ISSUE.BAD_FLAG,
2374
+ `options.type ${describe(options.type)} is not directed, undirected or mixed; mixed assumed`,
2375
+ { element: "options.type" }
2376
+ );
2377
+ }
2378
+ return "mixed";
2379
+ }
2380
+ function graphologyDirected(ctx, type, edges) {
2381
+ if (type !== "mixed") {
2382
+ return type === "directed";
2383
+ }
2384
+ const objects = edges.filter((edge) => isJsonObject(edge));
2385
+ const undirectedEdges = objects.filter((edge) => edge.undirected === true).length;
2386
+ return objects.length === 0 ? ctx.defaultDirected("graphology") : undirectedEdges < objects.length;
2387
+ }
2388
+ function pushGraphologyNode(ctx, record, element) {
2389
+ if (!isJsonObject(record)) {
2390
+ ctx.badElement("node", element);
2391
+ return;
2392
+ }
2393
+ const id = ctx.coerceId(hasKey(record, "key") ? record.key : void 0, element);
2394
+ if (id === null) {
2395
+ ctx.countSkipped("node");
2396
+ return;
2397
+ }
2398
+ pushNestedNode(ctx, id, record, "attributes", GRAPHOLOGY_NODE_KEYS, element);
2399
+ }
2400
+ function readGraphologyEdge(ctx, reading, record, element) {
2401
+ if (!isJsonObject(record)) {
2402
+ ctx.badElement("edge", element);
2403
+ return;
2404
+ }
2405
+ if (!present(record, "source") || !present(record, "target")) {
2406
+ ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2407
+ return;
2408
+ }
2409
+ try {
2410
+ const u = ctx.coerceId(record.source, `${element}.source`);
2411
+ const v = ctx.coerceId(record.target, `${element}.target`);
2412
+ if (u === null || v === null) {
2413
+ ctx.countSkipped("edge");
2414
+ return;
2353
2415
  }
2354
- if (!present(record, "source") || !present(record, "target")) {
2355
- ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2356
- continue;
2416
+ const kind = graphologyEdgeKind(ctx, reading, record, element);
2417
+ const attributes = graphologyEdgeAttributes(ctx, record, element);
2418
+ const idValue = ctx.edgeIdValue(reading.ids, record.key);
2419
+ const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(attributes), element);
2420
+ ctx.setEdgeId(reading.ids, edge, idValue);
2421
+ ctx.writeNested(ctx.edges, edge, record, attributes, GRAPHOLOGY_EDGE_KEYS, ctx.options.weightFrom, element);
2422
+ if (reading.allowSelfLoops === false && u === v) {
2423
+ reading.violations.selfLoops++;
2357
2424
  }
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);
2425
+ if (reading.pairs !== null) {
2426
+ const pair = `${kind} ${pairKey(u, v, kind === "directed")}`;
2427
+ reading.violations.parallels += reading.pairs.has(pair) ? 1 : 0;
2428
+ reading.pairs.add(pair);
2398
2429
  }
2430
+ } catch (err) {
2431
+ ctx.skip(err, "edge", element);
2399
2432
  }
2400
- reportGraphologyViolations(ctx, violations, type);
2401
- ctx.setMeta({ dialect: "graphology", allowSelfLoops }, { declaredMultigraph: multi, ...ctx.weightOriginPatch() });
2433
+ }
2434
+ function graphologyEdgeKind(ctx, reading, record, element) {
2435
+ const { type } = reading;
2436
+ if (type === "mixed") {
2437
+ return flagOf(record.undirected, `${element}.undirected`, false, ctx.report) ? "undirected" : "directed";
2438
+ }
2439
+ if (typeof record.undirected === "boolean" && record.undirected !== (type === "undirected")) {
2440
+ reading.violations.flags++;
2441
+ }
2442
+ return type;
2443
+ }
2444
+ function graphologyEdgeAttributes(ctx, record, element) {
2445
+ const { attributes } = record;
2446
+ if (attributes !== void 0 && attributes !== null && !isJsonObject(attributes)) {
2447
+ ctx.report.error(
2448
+ "validation-error",
2449
+ JSON_ISSUE.BAD_VALUE,
2450
+ `${element}: attributes must be an object, found ${describe(attributes)}`,
2451
+ { element }
2452
+ );
2453
+ }
2454
+ return isJsonObject(attributes) ? attributes : {};
2402
2455
  }
2403
2456
  function reportGraphologyViolations(ctx, violations, type) {
2404
2457
  const notes = [];
@@ -2457,23 +2510,7 @@ function importJgf(ctx, root) {
2457
2510
  );
2458
2511
  }
2459
2512
  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
- }
2513
+ const directed = jgfDirected(ctx, graph, edges);
2477
2514
  ctx.setHeader(directed);
2478
2515
  ctx.writeGraphDict(graph.metadata, "graph.metadata");
2479
2516
  const shape = {
@@ -2490,44 +2527,73 @@ function importJgf(ctx, root) {
2490
2527
  );
2491
2528
  if (isJsonObject(nodesRaw)) {
2492
2529
  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);
2530
+ pushJgfKeyedNode(ctx, key, nodesRaw[key], labelColumn);
2513
2531
  }
2514
2532
  } else {
2515
2533
  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);
2534
+ pushJgfListedNode(ctx, nodeRecords[i], labelColumn, `nodes[${i}]`);
2528
2535
  }
2529
2536
  }
2530
2537
  throwIfAborted(ctx.options.signal);
2538
+ const writeJgfEdge = jgfEdgeWriter(ctx, edges, hyperedges);
2539
+ for (let i = 0; i < edges.length; i++) {
2540
+ readJgfEdge(ctx, edges[i], `edges[${i}]`, directed, writeJgfEdge);
2541
+ }
2542
+ importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
2543
+ ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
2544
+ }
2545
+ function jgfDirected(ctx, graph, edges) {
2546
+ if (typeof graph.directed === "boolean") {
2547
+ return graph.directed;
2548
+ }
2549
+ if (ctx.explicitDefaultDirected) {
2550
+ return ctx.options.defaultDirected;
2551
+ }
2552
+ if (graph.directed !== void 0 && graph.directed !== null) {
2553
+ ctx.report.warning(
2554
+ "validation-error",
2555
+ JSON_ISSUE.BAD_FLAG,
2556
+ `graph.directed is ${describe(graph.directed)}, not a boolean`,
2557
+ { element: "graph.directed" }
2558
+ );
2559
+ }
2560
+ const objects = edges.filter((edge) => isJsonObject(edge));
2561
+ return objects.length === 0 || !objects.every((edge) => edge.directed === false);
2562
+ }
2563
+ function pushJgfKeyedNode(ctx, key, record, labelColumn) {
2564
+ const element = `nodes[${JSON.stringify(key)}]`;
2565
+ if (record !== null && !isJsonObject(record)) {
2566
+ ctx.badElement("node", element);
2567
+ return;
2568
+ }
2569
+ const id = ctx.coerceId(key, element);
2570
+ if (id === null) {
2571
+ ctx.countSkipped("node");
2572
+ return;
2573
+ }
2574
+ if (record !== null && hasKey(record, "id") && record.id !== key) {
2575
+ ctx.report.warning(
2576
+ "validation-error",
2577
+ JSON_ISSUE.INCONSISTENT,
2578
+ `${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}`,
2579
+ { element }
2580
+ );
2581
+ }
2582
+ pushJgfNode(ctx, id, record ?? {}, labelColumn, element);
2583
+ }
2584
+ function pushJgfListedNode(ctx, record, labelColumn, element) {
2585
+ if (!isJsonObject(record)) {
2586
+ ctx.badElement("node", element);
2587
+ return;
2588
+ }
2589
+ const id = ctx.coerceId(hasKey(record, "id") ? record.id : void 0, element);
2590
+ if (id === null) {
2591
+ ctx.countSkipped("node");
2592
+ return;
2593
+ }
2594
+ pushJgfNode(ctx, id, record, labelColumn, element);
2595
+ }
2596
+ function jgfEdgeWriter(ctx, edges, hyperedges) {
2531
2597
  const ids = ctx.declareEdgeIds([...edges, ...hyperedges], (edge) => edge.id, "id", false);
2532
2598
  const relationColumn = ctx.edges.declareIf(
2533
2599
  { name: "relation", dtype: "string", role: "kind", nullable: true },
@@ -2537,7 +2603,7 @@ function importJgf(ctx, root) {
2537
2603
  { name: "label", dtype: "string", role: "label", nullable: true },
2538
2604
  anyHas(edges, "label") || anyHas(hyperedges, "label")
2539
2605
  );
2540
- const writeJgfEdge = (record, u, v, kind, element, structural = JGF_EDGE_KEYS) => {
2606
+ return (record, u, v, kind, element, structural = JGF_EDGE_KEYS) => {
2541
2607
  const { metadata } = record;
2542
2608
  const dict = isJsonObject(metadata) ? metadata : {};
2543
2609
  const idValue = ctx.edgeIdValue(ids, record.id);
@@ -2546,38 +2612,34 @@ function importJgf(ctx, root) {
2546
2612
  ctx.writeStringField(ctx.edges, relationColumn, edge, record.relation, "relation", element);
2547
2613
  ctx.writeStringField(ctx.edges, edgeLabelColumn, edge, record.label, "label", element);
2548
2614
  if (metadata !== void 0 && metadata !== null && !isJsonObject(metadata)) {
2549
- report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
2615
+ ctx.report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
2550
2616
  element
2551
2617
  });
2552
2618
  }
2553
2619
  ctx.writeNested(ctx.edges, edge, record, dict, structural, ctx.options.weightFrom, element);
2554
2620
  };
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);
2621
+ }
2622
+ function readJgfEdge(ctx, record, element, directed, writeJgfEdge) {
2623
+ if (!isJsonObject(record)) {
2624
+ ctx.badElement("edge", element);
2625
+ return;
2626
+ }
2627
+ if (!present(record, "source") || !present(record, "target")) {
2628
+ ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
2629
+ return;
2630
+ }
2631
+ try {
2632
+ const u = ctx.coerceId(record.source, `${element}.source`);
2633
+ const v = ctx.coerceId(record.target, `${element}.target`);
2634
+ if (u === null || v === null) {
2635
+ ctx.countSkipped("edge");
2636
+ return;
2577
2637
  }
2638
+ const edgeDirected = flagOf(record.directed, `${element}.directed`, directed, ctx.report);
2639
+ writeJgfEdge(record, u, v, edgeDirected ? "directed" : "undirected", element);
2640
+ } catch (err) {
2641
+ ctx.skip(err, "edge", element);
2578
2642
  }
2579
- importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
2580
- ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
2581
2643
  }
2582
2644
  function jgfGraphOf(ctx, root) {
2583
2645
  const single = isJsonObject(root.graph);
@@ -2832,49 +2894,34 @@ function distinctMembers(ctx, members, element) {
2832
2894
  return distinct;
2833
2895
  }
2834
2896
  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
- }
2897
+ const { elements, extra } = cytoscapeRoot(ctx, root);
2855
2898
  const { nodes, edges } = cytoscapeSections(ctx, elements);
2856
2899
  ctx.setHeader(ctx.defaultDirected("cytoscape"));
2857
2900
  ctx.reportNodeIdFrom("cytoscape", "data.id");
2858
2901
  ctx.sink.reserve(nodes.length, edges.length);
2859
2902
  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
- );
2903
+ const reading = {
2904
+ positionColumn: ctx.nodes.declareIf(
2905
+ {
2906
+ name: POSITION_COLUMN,
2907
+ dtype: "f64",
2908
+ components: 3,
2909
+ role: "position",
2910
+ mutable: true,
2911
+ nullable: true,
2912
+ // 3D layouts written by Cytoscape-compatible tools carry a z
2913
+ extra: { sourceDims: nodes.some(hasPositionZ) ? 3 : 2, units: "file" },
2914
+ origin: { format: "json", namespace: "cytoscape" }
2915
+ },
2916
+ anyHas(nodes, "position")
2917
+ ),
2918
+ classesColumn: ctx.nodes.declareIf(
2919
+ { name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
2920
+ anyHas(nodes, "classes")
2921
+ ),
2922
+ parents: [],
2923
+ point: [0, 0, 0]
2924
+ };
2878
2925
  const parentColumn = ctx.nodes.declareIf(
2879
2926
  { name: PARENT_COLUMN, dtype: "u32", role: "parent", refersTo: "node", nullable: true },
2880
2927
  dataHas(nodes, "parent")
@@ -2883,77 +2930,104 @@ function importCytoscape(ctx, root) {
2883
2930
  { name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
2884
2931
  anyHas(edges, "classes")
2885
2932
  );
2886
- const parents = [];
2887
- const point = [0, 0, 0];
2888
2933
  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;
2934
+ readCytoscapeNode(ctx, reading, nodes[i], `nodes[${i}]`);
2935
+ }
2936
+ resolveCytoscapeParents(ctx, reading.parents, parentColumn);
2937
+ throwIfAborted(ctx.options.signal);
2938
+ importCytoscapeEdges(ctx, edges, edgeClassesColumn);
2939
+ ctx.setMeta({ dialect: "cytoscape", cytoscape: extra }, ctx.weightOriginPatch());
2940
+ }
2941
+ function cytoscapeRoot(ctx, root) {
2942
+ if (Array.isArray(root)) {
2943
+ return { elements: root };
2944
+ }
2945
+ if (!isJsonObject(root)) {
2946
+ ctx.report.fail(
2947
+ JSON_ISSUE.SHAPE,
2948
+ `a Cytoscape document must be an object or an array, found ${describe(root)}`
2949
+ );
2950
+ }
2951
+ ctx.writeGraphDict(root.data, "data");
2952
+ const rest = {};
2953
+ for (const key of Object.keys(root)) {
2954
+ if (key !== "elements" && key !== "data") {
2955
+ rest[key] = root[key];
2894
2956
  }
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");
2957
+ }
2958
+ return Object.keys(rest).length > 0 ? { elements: root.elements, extra: rest } : { elements: root.elements };
2959
+ }
2960
+ function readCytoscapeNode(ctx, reading, record, element) {
2961
+ const { report } = ctx;
2962
+ if (!isJsonObject(record) || !isJsonObject(record.data)) {
2963
+ ctx.badElement("node", element, "an element with a data object");
2964
+ return;
2965
+ }
2966
+ const { data } = record;
2967
+ const id = ctx.coerceId(hasKey(data, "id") ? data.id : void 0, element);
2968
+ if (id === null) {
2969
+ ctx.countSkipped("node");
2970
+ return;
2971
+ }
2972
+ const index = ctx.pushNode(id, element);
2973
+ if (index < 0) {
2974
+ return;
2975
+ }
2976
+ if (present(data, "source") && present(data, "target")) {
2977
+ report.warning(
2978
+ "validation-error",
2979
+ JSON_ISSUE.INCONSISTENT,
2980
+ `${element} has data.source and data.target, the shape of an edge, but its section or group says node; read as a node`,
2981
+ { element }
2982
+ );
2983
+ }
2984
+ try {
2985
+ writeCytoscapeData(ctx, reading, index, data, element);
2986
+ writeCytoscapePosition$1(ctx, reading, index, record.position, element);
2987
+ writeClasses(ctx, ctx.nodes, reading.classesColumn, index, record.classes, element);
2988
+ writeElementKeys(ctx.nodes, index, record, element);
2989
+ } catch (err) {
2990
+ report.recordError(err, { element: String(id) });
2991
+ }
2992
+ }
2993
+ function writeCytoscapeData(ctx, reading, index, data, element) {
2994
+ for (const key of Object.keys(data)) {
2995
+ if (key === "id") {
2899
2996
  continue;
2900
2997
  }
2901
- const index = ctx.pushNode(id, element);
2902
- if (index < 0) {
2998
+ if (key !== "parent") {
2999
+ ctx.nodes.write(index, key, data[key], SUFFIX.data, element);
2903
3000
  continue;
2904
3001
  }
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
- );
3002
+ const raw = data.parent;
3003
+ if (raw === void 0 || raw === null) {
3004
+ continue;
2912
3005
  }
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) });
3006
+ const parent = ctx.coerceId(raw, `${element}.data.parent`);
3007
+ if (parent !== null) {
3008
+ reading.parents.push({ index, parent, element });
2951
3009
  }
2952
3010
  }
2953
- resolveCytoscapeParents(ctx, parents, parentColumn);
2954
- throwIfAborted(ctx.options.signal);
2955
- importCytoscapeEdges(ctx, edges, edgeClassesColumn);
2956
- ctx.setMeta({ dialect: "cytoscape", cytoscape: extra }, ctx.weightOriginPatch());
3011
+ }
3012
+ function writeCytoscapePosition$1(ctx, reading, index, position, element) {
3013
+ if (position === void 0 || position === null) {
3014
+ return;
3015
+ }
3016
+ const z = isJsonObject(position) ? position.z ?? 0 : 0;
3017
+ if (isJsonObject(position) && isCoordinate(position.x) && isCoordinate(position.y) && isCoordinate(z)) {
3018
+ const { point } = reading;
3019
+ point[0] = position.x;
3020
+ point[1] = flipY(position.y);
3021
+ point[2] = z;
3022
+ ctx.nodes.set(reading.positionColumn, index, point);
3023
+ } else {
3024
+ ctx.report.error(
3025
+ "validation-error",
3026
+ JSON_ISSUE.BAD_VALUE,
3027
+ `${element}: position must be an object with numeric x and y (and z) that are finite numbers`,
3028
+ { element }
3029
+ );
3030
+ }
2957
3031
  }
2958
3032
  function resolveCytoscapeParents(ctx, parents, parentColumn) {
2959
3033
  const { report } = ctx;
@@ -3028,27 +3102,31 @@ function importCytoscapeEdges(ctx, edges, edgeClassesColumn) {
3028
3102
  ctx.missingEndpoint(element, `data.${present(data, "source") ? "target" : "source"}`);
3029
3103
  continue;
3030
3104
  }
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
- }
3105
+ importCytoscapeEdge(ctx, { ids, kind, edgeClassesColumn }, record, data, element);
3106
+ }
3107
+ }
3108
+ function importCytoscapeEdge(ctx, shared, record, data, element) {
3109
+ const { ids, kind, edgeClassesColumn } = shared;
3110
+ try {
3111
+ const u = ctx.coerceId(data.source, `${element}.data.source`);
3112
+ const v = ctx.coerceId(data.target, `${element}.data.target`);
3113
+ if (u === null || v === null) {
3114
+ ctx.countSkipped("edge");
3115
+ return;
3116
+ }
3117
+ const idValue = ctx.edgeIdValue(ids, data.id);
3118
+ const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(data), element);
3119
+ ctx.setEdgeId(ids, edge, idValue);
3120
+ const { weightFrom } = ctx.options;
3121
+ for (const key of Object.keys(data)) {
3122
+ if (key !== "id" && key !== "source" && key !== "target" && key !== weightFrom) {
3123
+ ctx.edges.write(edge, key, data[key], SUFFIX.data, element);
3046
3124
  }
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
3125
  }
3126
+ writeClasses(ctx, ctx.edges, edgeClassesColumn, edge, record.classes, element);
3127
+ writeElementKeys(ctx.edges, edge, record, element);
3128
+ } catch (err) {
3129
+ ctx.skip(err, "edge", element);
3052
3130
  }
3053
3131
  }
3054
3132
  function cytoscapeSections(ctx, elements) {
@@ -3566,21 +3644,7 @@ function writeNode(ctx, columns, vocabulary, record, row, element) {
3566
3644
  }
3567
3645
  function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
3568
3646
  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
- }
3647
+ writeDefinition(ctx, columns, meta.definition, row, unrecognized, path);
3584
3648
  const comments = strings$1(ctx, meta.comments, `${path}.comments`);
3585
3649
  if (comments.length > 0) {
3586
3650
  columns.node("comment", row, comments.join("\n"));
@@ -3609,6 +3673,22 @@ function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
3609
3673
  }
3610
3674
  }
3611
3675
  }
3676
+ function writeDefinition(ctx, columns, definition, row, unrecognized, path) {
3677
+ if (isJsonObject(definition)) {
3678
+ const xrefs = strings$1(ctx, definition.xrefs, `${path}.definition.xrefs`);
3679
+ if (typeof definition.val === "string") {
3680
+ columns.node("def", row, definition.val);
3681
+ columns.node("def.xrefs", row, xrefs);
3682
+ } else {
3683
+ badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
3684
+ }
3685
+ if (definition.meta !== void 0) {
3686
+ unrecognized["meta.definition.meta"] = definition.meta;
3687
+ }
3688
+ } else if (definition !== void 0 && definition !== null) {
3689
+ badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
3690
+ }
3691
+ }
3612
3692
  function synonymsOf(ctx, vocabulary, value, path) {
3613
3693
  if (value === void 0 || value === null) {
3614
3694
  return [];
@@ -5782,7 +5862,6 @@ function* writeCytoscape(snapshot, p) {
5782
5862
  const c = { w: new JsonWriter(resolved.indent), ids: snapshot.ids, nonfinite: { count: 0 } };
5783
5863
  const { w } = c;
5784
5864
  const parentSlots = /* @__PURE__ */ new Set(["parent"]);
5785
- const positionSlots = /* @__PURE__ */ new Set(["cytoscapePosition"]);
5786
5865
  w.open("{");
5787
5866
  w.key("elements");
5788
5867
  w.open("{");
@@ -5798,17 +5877,7 @@ function* writeCytoscape(snapshot, p) {
5798
5877
  writeSlots(c, p.nodes, i, parentSlots);
5799
5878
  writeSlots(c, p.nodes, i, ATTRIBUTE_SLOTS);
5800
5879
  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
- }
5880
+ writeCytoscapePosition(c, p.nodes, i);
5812
5881
  writeSlots(c, p.nodes, i, ELEMENT_SLOTS);
5813
5882
  w.close("}");
5814
5883
  yield w.take();
@@ -5845,17 +5914,34 @@ function* writeCytoscape(snapshot, p) {
5845
5914
  w.key("data");
5846
5915
  writeGraphObject(c, p);
5847
5916
  }
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
- }
5917
+ writeCytoscapeExtra(c, resolved.shape.cytoscape);
5856
5918
  w.close("}");
5857
5919
  yield w.take();
5858
5920
  }
5921
+ function writeCytoscapePosition(c, items, i) {
5922
+ const { w } = c;
5923
+ for (const item of items) {
5924
+ if (item.slot === "cytoscapePosition" && item.column.isSet(i)) {
5925
+ const value = item.column.value(i);
5926
+ const f32 = item.column.dtype === "f32";
5927
+ w.key("position");
5928
+ w.open("{");
5929
+ w.member("x", numberText(value[0], f32, c.nonfinite));
5930
+ w.member("y", numberText(flipY(value[1]), f32, c.nonfinite));
5931
+ w.close("}");
5932
+ }
5933
+ }
5934
+ }
5935
+ function writeCytoscapeExtra(c, extra) {
5936
+ if (extra === void 0) {
5937
+ return;
5938
+ }
5939
+ for (const key of Object.keys(extra)) {
5940
+ if (key !== "elements" && key !== "data") {
5941
+ c.w.member(key, valueText(extra[key], false, c.nonfinite));
5942
+ }
5943
+ }
5944
+ }
5859
5945
  function edgeIdGenerator(snapshot, p) {
5860
5946
  const used = /* @__PURE__ */ new Set();
5861
5947
  for (let i = 0; i < snapshot.nodeCount; i++) {
@@ -5946,4 +6032,4 @@ export {
5946
6032
  rankFormats as r,
5947
6033
  sniffFormat as s
5948
6034
  };
5949
- //# sourceMappingURL=exporter-CNJZF_BN.js.map
6035
+ //# sourceMappingURL=exporter-BqtmlxNr.js.map