@graphty/graph-io 0.3.24 → 0.3.26

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 (581) hide show
  1. package/README.md +49 -414
  2. package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
  3. package/dist/chunks/choose-BbJI55dx.js +56 -0
  4. package/dist/chunks/choose-BbJI55dx.js.map +1 -0
  5. package/dist/chunks/constants-BCsFsMj4.js +231 -0
  6. package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
  7. package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
  8. package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
  9. package/dist/chunks/export-BTI4yQgy.js +4333 -0
  10. package/dist/chunks/export-BTI4yQgy.js.map +1 -0
  11. package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
  12. package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
  13. package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
  14. package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
  15. package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
  16. package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
  17. package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
  18. package/dist/chunks/exporter-tne475KK.js.map +1 -0
  19. package/dist/chunks/importer-90YWhJoF.js +2811 -0
  20. package/dist/chunks/importer-90YWhJoF.js.map +1 -0
  21. package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
  22. package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
  23. package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
  24. package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
  25. package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
  26. package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
  27. package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
  28. package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
  29. package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
  30. package/dist/chunks/importer-DfVu6j59.js.map +1 -0
  31. package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
  32. package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
  33. package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
  34. package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
  35. package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
  36. package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
  37. package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
  38. package/dist/chunks/records-CQXT__mY.js.map +1 -0
  39. package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
  40. package/dist/chunks/text-DmcUs5_Q.js.map +1 -0
  41. package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
  42. package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
  43. package/dist/csv.js +951 -261
  44. package/dist/csv.js.map +1 -1
  45. package/dist/cx.js +6 -3
  46. package/dist/cx2.js +2 -2
  47. package/dist/cys.js +6 -3
  48. package/dist/dot.js +1 -1
  49. package/dist/gexf.js +554 -122
  50. package/dist/gexf.js.map +1 -1
  51. package/dist/gml.js +342 -85
  52. package/dist/gml.js.map +1 -1
  53. package/dist/graph-io.js +1105 -213
  54. package/dist/graph-io.js.map +1 -1
  55. package/dist/graphml.js +3 -2
  56. package/dist/graphml.js.map +1 -1
  57. package/dist/json.js +3 -2
  58. package/dist/neo4j.js +564 -157
  59. package/dist/neo4j.js.map +1 -1
  60. package/dist/obo.js +6 -3
  61. package/dist/pajek.js +1 -1
  62. package/dist/src/children.d.ts +18 -6
  63. package/dist/src/children.d.ts.map +1 -1
  64. package/dist/src/children.js +6 -3
  65. package/dist/src/children.js.map +1 -1
  66. package/dist/src/common/attributes.d.ts +29 -11
  67. package/dist/src/common/attributes.d.ts.map +1 -1
  68. package/dist/src/common/attributes.js +25 -7
  69. package/dist/src/common/attributes.js.map +1 -1
  70. package/dist/src/common/cell-budget.d.ts +9 -2
  71. package/dist/src/common/cell-budget.d.ts.map +1 -1
  72. package/dist/src/common/cell-budget.js +11 -3
  73. package/dist/src/common/cell-budget.js.map +1 -1
  74. package/dist/src/common/choose.d.ts +19 -0
  75. package/dist/src/common/choose.d.ts.map +1 -0
  76. package/dist/src/common/choose.js +72 -0
  77. package/dist/src/common/choose.js.map +1 -0
  78. package/dist/src/common/codes.d.ts +456 -66
  79. package/dist/src/common/codes.d.ts.map +1 -1
  80. package/dist/src/common/codes.js +458 -66
  81. package/dist/src/common/codes.js.map +1 -1
  82. package/dist/src/common/compare.d.ts +81 -0
  83. package/dist/src/common/compare.d.ts.map +1 -0
  84. package/dist/src/common/compare.js +394 -0
  85. package/dist/src/common/compare.js.map +1 -0
  86. package/dist/src/common/cx-export.d.ts +123 -0
  87. package/dist/src/common/cx-export.d.ts.map +1 -0
  88. package/dist/src/common/cx-export.js +334 -0
  89. package/dist/src/common/cx-export.js.map +1 -0
  90. package/dist/src/common/declared-types.d.ts +22 -2
  91. package/dist/src/common/declared-types.d.ts.map +1 -1
  92. package/dist/src/common/declared-types.js +19 -1
  93. package/dist/src/common/declared-types.js.map +1 -1
  94. package/dist/src/common/direction.d.ts +74 -50
  95. package/dist/src/common/direction.d.ts.map +1 -1
  96. package/dist/src/common/direction.js +47 -27
  97. package/dist/src/common/direction.js.map +1 -1
  98. package/dist/src/common/escape.d.ts +21 -9
  99. package/dist/src/common/escape.d.ts.map +1 -1
  100. package/dist/src/common/escape.js +33 -17
  101. package/dist/src/common/escape.js.map +1 -1
  102. package/dist/src/common/export.d.ts +144 -32
  103. package/dist/src/common/export.d.ts.map +1 -1
  104. package/dist/src/common/export.js +216 -42
  105. package/dist/src/common/export.js.map +1 -1
  106. package/dist/src/common/format.d.ts +23 -1
  107. package/dist/src/common/format.d.ts.map +1 -1
  108. package/dist/src/common/format.js +26 -1
  109. package/dist/src/common/format.js.map +1 -1
  110. package/dist/src/common/ids.d.ts +9 -2
  111. package/dist/src/common/ids.d.ts.map +1 -1
  112. package/dist/src/common/ids.js +6 -2
  113. package/dist/src/common/ids.js.map +1 -1
  114. package/dist/src/common/input.d.ts +122 -28
  115. package/dist/src/common/input.d.ts.map +1 -1
  116. package/dist/src/common/input.js +890 -124
  117. package/dist/src/common/input.js.map +1 -1
  118. package/dist/src/common/json-elements.d.ts +144 -20
  119. package/dist/src/common/json-elements.d.ts.map +1 -1
  120. package/dist/src/common/json-elements.js +868 -188
  121. package/dist/src/common/json-elements.js.map +1 -1
  122. package/dist/src/common/line-format.d.ts +90 -0
  123. package/dist/src/common/line-format.d.ts.map +1 -0
  124. package/dist/src/common/line-format.js +185 -0
  125. package/dist/src/common/line-format.js.map +1 -0
  126. package/dist/src/common/lists.d.ts +6 -1
  127. package/dist/src/common/lists.d.ts.map +1 -1
  128. package/dist/src/common/lists.js +2 -0
  129. package/dist/src/common/lists.js.map +1 -1
  130. package/dist/src/common/ontology-export.d.ts +167 -0
  131. package/dist/src/common/ontology-export.d.ts.map +1 -0
  132. package/dist/src/common/ontology-export.js +359 -0
  133. package/dist/src/common/ontology-export.js.map +1 -0
  134. package/dist/src/common/ontology.d.ts +25 -3
  135. package/dist/src/common/ontology.d.ts.map +1 -1
  136. package/dist/src/common/ontology.js +30 -9
  137. package/dist/src/common/ontology.js.map +1 -1
  138. package/dist/src/common/options.d.ts +62 -12
  139. package/dist/src/common/options.d.ts.map +1 -1
  140. package/dist/src/common/options.js +89 -11
  141. package/dist/src/common/options.js.map +1 -1
  142. package/dist/src/common/plural.d.ts +31 -0
  143. package/dist/src/common/plural.d.ts.map +1 -0
  144. package/dist/src/common/plural.js +46 -0
  145. package/dist/src/common/plural.js.map +1 -0
  146. package/dist/src/common/report.d.ts +72 -14
  147. package/dist/src/common/report.d.ts.map +1 -1
  148. package/dist/src/common/report.js +146 -22
  149. package/dist/src/common/report.js.map +1 -1
  150. package/dist/src/common/temporal.d.ts +22 -5
  151. package/dist/src/common/temporal.d.ts.map +1 -1
  152. package/dist/src/common/temporal.js +13 -2
  153. package/dist/src/common/temporal.js.map +1 -1
  154. package/dist/src/common/text.d.ts +39 -23
  155. package/dist/src/common/text.d.ts.map +1 -1
  156. package/dist/src/common/text.js +51 -21
  157. package/dist/src/common/text.js.map +1 -1
  158. package/dist/src/common/weights.d.ts +37 -4
  159. package/dist/src/common/weights.d.ts.map +1 -1
  160. package/dist/src/common/weights.js +61 -2
  161. package/dist/src/common/weights.js.map +1 -1
  162. package/dist/src/common/writer.d.ts +19 -3
  163. package/dist/src/common/writer.d.ts.map +1 -1
  164. package/dist/src/common/writer.js +30 -2
  165. package/dist/src/common/writer.js.map +1 -1
  166. package/dist/src/common/xml.d.ts +125 -9
  167. package/dist/src/common/xml.d.ts.map +1 -1
  168. package/dist/src/common/xml.js +400 -83
  169. package/dist/src/common/xml.js.map +1 -1
  170. package/dist/src/common/zip.d.ts +44 -4
  171. package/dist/src/common/zip.d.ts.map +1 -1
  172. package/dist/src/common/zip.js +134 -5
  173. package/dist/src/common/zip.js.map +1 -1
  174. package/dist/src/formats/csv/exporter.d.ts +80 -24
  175. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  176. package/dist/src/formats/csv/exporter.js +145 -32
  177. package/dist/src/formats/csv/exporter.js.map +1 -1
  178. package/dist/src/formats/csv/header.d.ts +38 -9
  179. package/dist/src/formats/csv/header.d.ts.map +1 -1
  180. package/dist/src/formats/csv/header.js +46 -10
  181. package/dist/src/formats/csv/header.js.map +1 -1
  182. package/dist/src/formats/csv/importer.d.ts +187 -37
  183. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  184. package/dist/src/formats/csv/importer.js +835 -204
  185. package/dist/src/formats/csv/importer.js.map +1 -1
  186. package/dist/src/formats/csv/index.d.ts +100 -19
  187. package/dist/src/formats/csv/index.d.ts.map +1 -1
  188. package/dist/src/formats/csv/index.js +94 -21
  189. package/dist/src/formats/csv/index.js.map +1 -1
  190. package/dist/src/formats/csv/records.d.ts +95 -10
  191. package/dist/src/formats/csv/records.d.ts.map +1 -1
  192. package/dist/src/formats/csv/records.js +333 -122
  193. package/dist/src/formats/csv/records.js.map +1 -1
  194. package/dist/src/formats/csv/values.d.ts +1 -0
  195. package/dist/src/formats/csv/values.d.ts.map +1 -1
  196. package/dist/src/formats/csv/values.js +1 -0
  197. package/dist/src/formats/csv/values.js.map +1 -1
  198. package/dist/src/formats/cx/exporter.d.ts +102 -0
  199. package/dist/src/formats/cx/exporter.d.ts.map +1 -0
  200. package/dist/src/formats/cx/exporter.js +1217 -0
  201. package/dist/src/formats/cx/exporter.js.map +1 -0
  202. package/dist/src/formats/cx/importer.d.ts +79 -32
  203. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  204. package/dist/src/formats/cx/importer.js +680 -285
  205. package/dist/src/formats/cx/importer.js.map +1 -1
  206. package/dist/src/formats/cx/index.d.ts +4 -3
  207. package/dist/src/formats/cx/index.d.ts.map +1 -1
  208. package/dist/src/formats/cx/index.js +4 -3
  209. package/dist/src/formats/cx/index.js.map +1 -1
  210. package/dist/src/formats/cx2/exporter.d.ts +29 -11
  211. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  212. package/dist/src/formats/cx2/exporter.js +39 -268
  213. package/dist/src/formats/cx2/exporter.js.map +1 -1
  214. package/dist/src/formats/cx2/importer.d.ts +78 -28
  215. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  216. package/dist/src/formats/cx2/importer.js +226 -79
  217. package/dist/src/formats/cx2/importer.js.map +1 -1
  218. package/dist/src/formats/cx2/index.d.ts +2 -1
  219. package/dist/src/formats/cx2/index.d.ts.map +1 -1
  220. package/dist/src/formats/cx2/index.js +2 -1
  221. package/dist/src/formats/cx2/index.js.map +1 -1
  222. package/dist/src/formats/cys/constants.d.ts +66 -17
  223. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  224. package/dist/src/formats/cys/constants.js +59 -18
  225. package/dist/src/formats/cys/constants.js.map +1 -1
  226. package/dist/src/formats/cys/exporter.d.ts +118 -0
  227. package/dist/src/formats/cys/exporter.d.ts.map +1 -0
  228. package/dist/src/formats/cys/exporter.js +1072 -0
  229. package/dist/src/formats/cys/exporter.js.map +1 -0
  230. package/dist/src/formats/cys/importer.d.ts +22 -8
  231. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  232. package/dist/src/formats/cys/importer.js +510 -149
  233. package/dist/src/formats/cys/importer.js.map +1 -1
  234. package/dist/src/formats/cys/index.d.ts +4 -2
  235. package/dist/src/formats/cys/index.d.ts.map +1 -1
  236. package/dist/src/formats/cys/index.js +4 -2
  237. package/dist/src/formats/cys/index.js.map +1 -1
  238. package/dist/src/formats/cys/session.d.ts +46 -7
  239. package/dist/src/formats/cys/session.d.ts.map +1 -1
  240. package/dist/src/formats/cys/session.js +98 -24
  241. package/dist/src/formats/cys/session.js.map +1 -1
  242. package/dist/src/formats/cys/tables.d.ts +9 -2
  243. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  244. package/dist/src/formats/cys/tables.js +29 -7
  245. package/dist/src/formats/cys/tables.js.map +1 -1
  246. package/dist/src/formats/dot/exporter.d.ts +42 -14
  247. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  248. package/dist/src/formats/dot/exporter.js +56 -29
  249. package/dist/src/formats/dot/exporter.js.map +1 -1
  250. package/dist/src/formats/dot/importer.d.ts +91 -29
  251. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  252. package/dist/src/formats/dot/importer.js +190 -39
  253. package/dist/src/formats/dot/importer.js.map +1 -1
  254. package/dist/src/formats/dot/index.d.ts +2 -1
  255. package/dist/src/formats/dot/index.d.ts.map +1 -1
  256. package/dist/src/formats/dot/index.js +2 -1
  257. package/dist/src/formats/dot/index.js.map +1 -1
  258. package/dist/src/formats/dot/names.d.ts +44 -11
  259. package/dist/src/formats/dot/names.d.ts.map +1 -1
  260. package/dist/src/formats/dot/names.js +44 -11
  261. package/dist/src/formats/dot/names.js.map +1 -1
  262. package/dist/src/formats/dot/tokenizer.d.ts +9 -2
  263. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
  264. package/dist/src/formats/dot/tokenizer.js +20 -5
  265. package/dist/src/formats/dot/tokenizer.js.map +1 -1
  266. package/dist/src/formats/gexf/exporter.d.ts +46 -15
  267. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  268. package/dist/src/formats/gexf/exporter.js +45 -15
  269. package/dist/src/formats/gexf/exporter.js.map +1 -1
  270. package/dist/src/formats/gexf/importer.d.ts +87 -23
  271. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  272. package/dist/src/formats/gexf/importer.js +471 -90
  273. package/dist/src/formats/gexf/importer.js.map +1 -1
  274. package/dist/src/formats/gexf/index.d.ts +84 -21
  275. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  276. package/dist/src/formats/gexf/index.js +80 -23
  277. package/dist/src/formats/gexf/index.js.map +1 -1
  278. package/dist/src/formats/gexf/schema.d.ts +67 -15
  279. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  280. package/dist/src/formats/gexf/schema.js +59 -13
  281. package/dist/src/formats/gexf/schema.js.map +1 -1
  282. package/dist/src/formats/gml/exporter.d.ts +69 -21
  283. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/gml/exporter.js +74 -29
  285. package/dist/src/formats/gml/exporter.js.map +1 -1
  286. package/dist/src/formats/gml/importer.d.ts +116 -25
  287. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  288. package/dist/src/formats/gml/importer.js +290 -61
  289. package/dist/src/formats/gml/importer.js.map +1 -1
  290. package/dist/src/formats/gml/index.d.ts +87 -24
  291. package/dist/src/formats/gml/index.d.ts.map +1 -1
  292. package/dist/src/formats/gml/index.js +79 -26
  293. package/dist/src/formats/gml/index.js.map +1 -1
  294. package/dist/src/formats/gml/syntax.d.ts +67 -18
  295. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  296. package/dist/src/formats/gml/syntax.js +108 -26
  297. package/dist/src/formats/gml/syntax.js.map +1 -1
  298. package/dist/src/formats/graphml/constants.d.ts +174 -44
  299. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  300. package/dist/src/formats/graphml/constants.js +165 -44
  301. package/dist/src/formats/graphml/constants.js.map +1 -1
  302. package/dist/src/formats/graphml/exporter.d.ts +17 -9
  303. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  304. package/dist/src/formats/graphml/exporter.js +33 -12
  305. package/dist/src/formats/graphml/exporter.js.map +1 -1
  306. package/dist/src/formats/graphml/importer.d.ts +19 -7
  307. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  308. package/dist/src/formats/graphml/importer.js +466 -39
  309. package/dist/src/formats/graphml/importer.js.map +1 -1
  310. package/dist/src/formats/graphml/index.d.ts +2 -1
  311. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  312. package/dist/src/formats/graphml/index.js +2 -1
  313. package/dist/src/formats/graphml/index.js.map +1 -1
  314. package/dist/src/formats/graphml/tree.d.ts +6 -2
  315. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  316. package/dist/src/formats/graphml/tree.js +6 -2
  317. package/dist/src/formats/graphml/tree.js.map +1 -1
  318. package/dist/src/formats/graphml/yfiles.d.ts +8 -3
  319. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  320. package/dist/src/formats/graphml/yfiles.js +36 -15
  321. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  322. package/dist/src/formats/json/dialect.d.ts +88 -24
  323. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  324. package/dist/src/formats/json/dialect.js +109 -19
  325. package/dist/src/formats/json/dialect.js.map +1 -1
  326. package/dist/src/formats/json/exporter.d.ts +134 -22
  327. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  328. package/dist/src/formats/json/exporter.js +135 -54
  329. package/dist/src/formats/json/exporter.js.map +1 -1
  330. package/dist/src/formats/json/importer.d.ts +173 -52
  331. package/dist/src/formats/json/importer.d.ts.map +1 -1
  332. package/dist/src/formats/json/importer.js +899 -220
  333. package/dist/src/formats/json/importer.js.map +1 -1
  334. package/dist/src/formats/json/index.d.ts +3 -2
  335. package/dist/src/formats/json/index.d.ts.map +1 -1
  336. package/dist/src/formats/json/index.js +3 -2
  337. package/dist/src/formats/json/index.js.map +1 -1
  338. package/dist/src/formats/json/obographs-export.d.ts +68 -0
  339. package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
  340. package/dist/src/formats/json/obographs-export.js +941 -0
  341. package/dist/src/formats/json/obographs-export.js.map +1 -0
  342. package/dist/src/formats/json/obographs.d.ts +26 -0
  343. package/dist/src/formats/json/obographs.d.ts.map +1 -1
  344. package/dist/src/formats/json/obographs.js +297 -80
  345. package/dist/src/formats/json/obographs.js.map +1 -1
  346. package/dist/src/formats/neo4j/exporter.d.ts +109 -21
  347. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  348. package/dist/src/formats/neo4j/exporter.js +238 -85
  349. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  350. package/dist/src/formats/neo4j/header.d.ts +17 -4
  351. package/dist/src/formats/neo4j/header.d.ts.map +1 -1
  352. package/dist/src/formats/neo4j/header.js +36 -4
  353. package/dist/src/formats/neo4j/header.js.map +1 -1
  354. package/dist/src/formats/neo4j/importer.d.ts +107 -27
  355. package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
  356. package/dist/src/formats/neo4j/importer.js +415 -63
  357. package/dist/src/formats/neo4j/importer.js.map +1 -1
  358. package/dist/src/formats/neo4j/index.d.ts +73 -23
  359. package/dist/src/formats/neo4j/index.d.ts.map +1 -1
  360. package/dist/src/formats/neo4j/index.js +65 -25
  361. package/dist/src/formats/neo4j/index.js.map +1 -1
  362. package/dist/src/formats/obo/exporter.d.ts +150 -0
  363. package/dist/src/formats/obo/exporter.d.ts.map +1 -0
  364. package/dist/src/formats/obo/exporter.js +1736 -0
  365. package/dist/src/formats/obo/exporter.js.map +1 -0
  366. package/dist/src/formats/obo/importer.d.ts +95 -19
  367. package/dist/src/formats/obo/importer.d.ts.map +1 -1
  368. package/dist/src/formats/obo/importer.js +475 -104
  369. package/dist/src/formats/obo/importer.js.map +1 -1
  370. package/dist/src/formats/obo/index.d.ts +6 -3
  371. package/dist/src/formats/obo/index.d.ts.map +1 -1
  372. package/dist/src/formats/obo/index.js +6 -3
  373. package/dist/src/formats/obo/index.js.map +1 -1
  374. package/dist/src/formats/obo/syntax.d.ts +108 -4
  375. package/dist/src/formats/obo/syntax.d.ts.map +1 -1
  376. package/dist/src/formats/obo/syntax.js +211 -34
  377. package/dist/src/formats/obo/syntax.js.map +1 -1
  378. package/dist/src/formats/pajek/exporter.d.ts +54 -16
  379. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  380. package/dist/src/formats/pajek/exporter.js +66 -34
  381. package/dist/src/formats/pajek/exporter.js.map +1 -1
  382. package/dist/src/formats/pajek/importer.d.ts +84 -22
  383. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  384. package/dist/src/formats/pajek/importer.js +303 -83
  385. package/dist/src/formats/pajek/importer.js.map +1 -1
  386. package/dist/src/formats/pajek/index.d.ts +2 -1
  387. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  388. package/dist/src/formats/pajek/index.js +2 -1
  389. package/dist/src/formats/pajek/index.js.map +1 -1
  390. package/dist/src/formats/pajek/syntax.d.ts +77 -14
  391. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  392. package/dist/src/formats/pajek/syntax.js +183 -51
  393. package/dist/src/formats/pajek/syntax.js.map +1 -1
  394. package/dist/src/formats/xgmml/columns.d.ts +1 -0
  395. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  396. package/dist/src/formats/xgmml/columns.js +4 -0
  397. package/dist/src/formats/xgmml/columns.js.map +1 -1
  398. package/dist/src/formats/xgmml/constants.d.ts +186 -56
  399. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  400. package/dist/src/formats/xgmml/constants.js +181 -57
  401. package/dist/src/formats/xgmml/constants.js.map +1 -1
  402. package/dist/src/formats/xgmml/document.d.ts +65 -11
  403. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  404. package/dist/src/formats/xgmml/document.js +157 -28
  405. package/dist/src/formats/xgmml/document.js.map +1 -1
  406. package/dist/src/formats/xgmml/emit.d.ts +61 -3
  407. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  408. package/dist/src/formats/xgmml/emit.js +129 -26
  409. package/dist/src/formats/xgmml/emit.js.map +1 -1
  410. package/dist/src/formats/xgmml/exporter.d.ts +13 -6
  411. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  412. package/dist/src/formats/xgmml/exporter.js +20 -21
  413. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  414. package/dist/src/formats/xgmml/importer.d.ts +33 -12
  415. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  416. package/dist/src/formats/xgmml/importer.js +35 -72
  417. package/dist/src/formats/xgmml/importer.js.map +1 -1
  418. package/dist/src/formats/xgmml/index.d.ts +1 -0
  419. package/dist/src/formats/xgmml/index.d.ts.map +1 -1
  420. package/dist/src/formats/xgmml/index.js +1 -0
  421. package/dist/src/formats/xgmml/index.js.map +1 -1
  422. package/dist/src/formats/xgmml/values.d.ts +8 -1
  423. package/dist/src/formats/xgmml/values.d.ts.map +1 -1
  424. package/dist/src/formats/xgmml/values.js +7 -2
  425. package/dist/src/formats/xgmml/values.js.map +1 -1
  426. package/dist/src/index.d.ts +23 -18
  427. package/dist/src/index.d.ts.map +1 -1
  428. package/dist/src/index.js +28 -16
  429. package/dist/src/index.js.map +1 -1
  430. package/dist/src/registry.d.ts +478 -92
  431. package/dist/src/registry.d.ts.map +1 -1
  432. package/dist/src/registry.js +807 -88
  433. package/dist/src/registry.js.map +1 -1
  434. package/dist/src/sniff.d.ts +61 -19
  435. package/dist/src/sniff.d.ts.map +1 -1
  436. package/dist/src/sniff.js +121 -29
  437. package/dist/src/sniff.js.map +1 -1
  438. package/dist/src/types.d.ts +362 -112
  439. package/dist/src/types.d.ts.map +1 -1
  440. package/dist/src/types.js +28 -7
  441. package/dist/src/types.js.map +1 -1
  442. package/dist/xgmml.js +2 -2
  443. package/docs/samples/README.md +25 -0
  444. package/docs/samples/got-edges.csv +353 -0
  445. package/docs/samples/got-network.graphml +1384 -0
  446. package/docs/samples/got-nodes.csv +108 -0
  447. package/docs/samples/got.cx +930 -0
  448. package/docs/samples/got.cx2 +465 -0
  449. package/docs/samples/got.gexf +471 -0
  450. package/docs/samples/got.gml +2650 -0
  451. package/docs/samples/got.json +2546 -0
  452. package/docs/samples/got.net +461 -0
  453. package/docs/samples/movies-nodes.csv +9 -0
  454. package/docs/samples/movies-rels.csv +8 -0
  455. package/docs/samples/networks.cys +0 -0
  456. package/docs/samples/proteins.xgmml +9 -0
  457. package/docs/samples/teams.gv +24 -0
  458. package/docs/samples/vehicles.obo +25 -0
  459. package/package.json +9 -4
  460. package/src/children.ts +18 -6
  461. package/src/common/attributes.ts +29 -11
  462. package/src/common/cell-budget.ts +11 -3
  463. package/src/common/choose.ts +89 -0
  464. package/src/common/codes.ts +490 -66
  465. package/src/common/compare.ts +472 -0
  466. package/src/common/cx-export.ts +432 -0
  467. package/src/common/declared-types.ts +38 -4
  468. package/src/common/direction.ts +78 -51
  469. package/src/common/escape.ts +33 -17
  470. package/src/common/export.ts +284 -47
  471. package/src/common/format.ts +30 -1
  472. package/src/common/ids.ts +14 -3
  473. package/src/common/input.ts +1057 -134
  474. package/src/common/json-elements.ts +1034 -198
  475. package/src/common/line-format.ts +249 -0
  476. package/src/common/lists.ts +6 -1
  477. package/src/common/ontology-export.ts +461 -0
  478. package/src/common/ontology.ts +31 -9
  479. package/src/common/options.ts +110 -15
  480. package/src/common/plural.ts +49 -0
  481. package/src/common/report.ts +168 -25
  482. package/src/common/temporal.ts +22 -5
  483. package/src/common/text.ts +62 -23
  484. package/src/common/weights.ts +74 -4
  485. package/src/common/writer.ts +37 -3
  486. package/src/common/xml.ts +477 -88
  487. package/src/common/zip.ts +169 -7
  488. package/src/formats/csv/exporter.ts +201 -46
  489. package/src/formats/csv/header.ts +50 -11
  490. package/src/formats/csv/importer.ts +1133 -245
  491. package/src/formats/csv/index.ts +106 -19
  492. package/src/formats/csv/records.ts +396 -122
  493. package/src/formats/csv/values.ts +1 -0
  494. package/src/formats/cx/exporter.ts +1483 -0
  495. package/src/formats/cx/importer.ts +888 -300
  496. package/src/formats/cx/index.ts +4 -3
  497. package/src/formats/cx2/exporter.ts +61 -338
  498. package/src/formats/cx2/importer.ts +317 -86
  499. package/src/formats/cx2/index.ts +2 -1
  500. package/src/formats/cys/constants.ts +62 -17
  501. package/src/formats/cys/exporter.ts +1368 -0
  502. package/src/formats/cys/importer.ts +659 -157
  503. package/src/formats/cys/index.ts +4 -2
  504. package/src/formats/cys/session.ts +139 -31
  505. package/src/formats/cys/tables.ts +47 -9
  506. package/src/formats/dot/exporter.ts +83 -37
  507. package/src/formats/dot/importer.ts +248 -54
  508. package/src/formats/dot/index.ts +2 -1
  509. package/src/formats/dot/names.ts +44 -11
  510. package/src/formats/dot/tokenizer.ts +25 -6
  511. package/src/formats/gexf/exporter.ts +57 -18
  512. package/src/formats/gexf/importer.ts +636 -105
  513. package/src/formats/gexf/index.ts +90 -21
  514. package/src/formats/gexf/schema.ts +67 -15
  515. package/src/formats/gml/exporter.ts +90 -36
  516. package/src/formats/gml/importer.ts +388 -67
  517. package/src/formats/gml/index.ts +85 -24
  518. package/src/formats/gml/syntax.ts +111 -26
  519. package/src/formats/graphml/constants.ts +178 -44
  520. package/src/formats/graphml/exporter.ts +52 -18
  521. package/src/formats/graphml/importer.ts +640 -60
  522. package/src/formats/graphml/index.ts +2 -1
  523. package/src/formats/graphml/tree.ts +6 -2
  524. package/src/formats/graphml/yfiles.ts +37 -15
  525. package/src/formats/json/dialect.ts +128 -29
  526. package/src/formats/json/exporter.ts +205 -68
  527. package/src/formats/json/importer.ts +1163 -253
  528. package/src/formats/json/index.ts +3 -1
  529. package/src/formats/json/obographs-export.ts +1197 -0
  530. package/src/formats/json/obographs.ts +353 -92
  531. package/src/formats/neo4j/exporter.ts +320 -101
  532. package/src/formats/neo4j/header.ts +44 -6
  533. package/src/formats/neo4j/importer.ts +512 -73
  534. package/src/formats/neo4j/index.ts +75 -23
  535. package/src/formats/obo/exporter.ts +2210 -0
  536. package/src/formats/obo/importer.ts +622 -109
  537. package/src/formats/obo/index.ts +6 -3
  538. package/src/formats/obo/syntax.ts +232 -37
  539. package/src/formats/pajek/exporter.ts +89 -41
  540. package/src/formats/pajek/importer.ts +407 -93
  541. package/src/formats/pajek/index.ts +2 -1
  542. package/src/formats/pajek/syntax.ts +213 -52
  543. package/src/formats/xgmml/columns.ts +10 -0
  544. package/src/formats/xgmml/constants.ts +183 -56
  545. package/src/formats/xgmml/document.ts +212 -34
  546. package/src/formats/xgmml/emit.ts +175 -34
  547. package/src/formats/xgmml/exporter.ts +35 -27
  548. package/src/formats/xgmml/importer.ts +64 -86
  549. package/src/formats/xgmml/index.ts +1 -0
  550. package/src/formats/xgmml/values.ts +11 -3
  551. package/src/index.ts +81 -11
  552. package/src/registry.ts +1121 -135
  553. package/src/sniff.ts +163 -32
  554. package/src/types.ts +385 -114
  555. package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
  556. package/dist/chunks/export-Bh60Dv-n.js +0 -582
  557. package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
  558. package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
  559. package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
  560. package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
  561. package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
  562. package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
  563. package/dist/chunks/importer-DET1tg6s.js.map +0 -1
  564. package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
  565. package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
  566. package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
  567. package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
  568. package/dist/chunks/importer-eUREhBGj.js.map +0 -1
  569. package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
  570. package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
  571. package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
  572. package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
  573. package/dist/chunks/ontology-BnrJ4I98.js +0 -113
  574. package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
  575. package/dist/chunks/records-dbRkxwaq.js.map +0 -1
  576. package/dist/chunks/report-B1z4WT9e.js +0 -2372
  577. package/dist/chunks/report-B1z4WT9e.js.map +0 -1
  578. package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
  579. package/dist/chunks/weights-Dzba96G3.js +0 -176
  580. package/dist/chunks/weights-Dzba96G3.js.map +0 -1
  581. package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
@@ -4,7 +4,7 @@
4
4
  * <attributes>` in the generic one) or, with `table: "nodes"`, the node table (`Id,Label,
5
5
  * <attributes>`), RFC 4180 quoted, one row per logical edge with expanded pairs folded back
6
6
  * through the `pair` role column; or, with `table: "adjacency"`, an adjacency table: a node and its
7
- * neighbours per row (`id:weight` for an explicit weight), no header, no attribute columns.
7
+ * neighbors per row (`id:weight` for an explicit weight), no header, no attribute columns.
8
8
  *
9
9
  * What survives a re-import exactly: ids (as text under the canonical rule), topology and
10
10
  * orientation, explicit weights (blank cells for defaulted ones), the per-row direction of the
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * The adjacency table keeps ids, the node order, isolated nodes, the edge order, orientation and
20
20
  * explicit weights: consecutive edges with the same source share a row, a node the rows would
21
- * otherwise introduce out of index order gets a row of its own first, and a neighbour id holding a
21
+ * otherwise introduce out of index order gets a row of its own first, and a neighbor id holding a
22
22
  * colon is written `id:` when it has no weight so the importer does not read its tail as one.
23
23
  */
24
24
 
@@ -31,7 +31,8 @@ import { capabilities, checkCapabilities, countMixedEdges, LOSS } from "../../co
31
31
  import { formatDecimal, formatInteger } from "../../common/format.js";
32
32
  import { canonicalId } from "../../common/ids.js";
33
33
  import { joinListText } from "../../common/lists.js";
34
- import { type ResolvedExportOptions, resolveExportOptions } from "../../common/options.js";
34
+ import { otherFormatDialect, type ResolvedExportOptions, resolveExportOptions } from "../../common/options.js";
35
+ import { agree, plural } from "../../common/plural.js";
35
36
  import { inferTextDtype, type TextDtype } from "../../common/text.js";
36
37
  import { type ExplicitWeights, explicitWeights } from "../../common/weights.js";
37
38
  import { encodeChunks, joinText } from "../../common/writer.js";
@@ -39,31 +40,59 @@ import { type CommonExportOptions, type ExportCapabilities, type GraphExporter,
39
40
  import { EDGE_ID_NAMES, findColumn, LABEL_NAMES } from "./header.js";
40
41
  import { DELIMITER_CANDIDATES } from "./records.js";
41
42
 
42
- /** The format-specific options of the CSV exporter. */
43
- export interface CsvExportOptions {
43
+ /**
44
+ * The format-specific options of the CSV exporter.
45
+ * @category Built-in formats
46
+ */
47
+ export interface CsvExportOptions extends CommonExportOptions {
44
48
  /**
45
- * The header spelling: "gephi" (default) writes `Source,Target,Type,...,Weight` with the per-row
46
- * direction; "generic" writes `source,target,...,weight` and no direction column.
49
+ * The header spelling: "gephi" writes `Source,Target,Type,...,Weight`, with each edge's
50
+ * direction in `Type`; "generic" writes `source,target,...,weight` and no direction column. A JSON
51
+ * dialect name, from an options object shared with JSON saves, is ignored.
52
+ * @defaultValue "gephi"
47
53
  */
48
54
  dialect?: "gephi" | "generic" | undefined;
49
55
  /**
50
- * Which table to write: the edge table (default), the node table, or an adjacency table (a node
51
- * and its neighbours per row; read back with the importer's `table: "adjacency"`).
56
+ * Which table to write. "edges": one edge per row, with the edge attributes; isolated nodes and
57
+ * node attributes are not in it. "nodes": one node per row, with the node attributes and no
58
+ * edges. "adjacency": a node and its neighbors per row, which keeps every node and the node
59
+ * order but no attributes (read it back with `table: "adjacency"`). To keep both nodes and
60
+ * edges, write the node table and the edge table to two files and read them back with the
61
+ * `nodes` import option.
62
+ * @defaultValue "edges"
52
63
  */
53
64
  table?: "edges" | "nodes" | "adjacency" | undefined;
54
- /** The field delimiter; "," by default. */
65
+ /**
66
+ * The field delimiter.
67
+ * @defaultValue ","
68
+ */
55
69
  delimiter?: string | undefined;
56
- /** The line terminator; "\n" by default. */
70
+ /**
71
+ * The line terminator.
72
+ * @defaultValue "\n"
73
+ */
57
74
  newline?: "\n" | "\r\n" | undefined;
58
- /** Whether to write the header row; true by default (an adjacency table never has one). */
75
+ /**
76
+ * Whether to write the header row (an adjacency table never has one). A file without a header is
77
+ * read back by position: source, target, weight, then unnamed columns. checkExport() returns
78
+ * W_CSV_HEADERLESS when the table has other columns; for a plain headerless edge list, pass
79
+ * `dialect: "generic"` and write a graph whose edges have only weights.
80
+ * @defaultValue true
81
+ */
59
82
  header?: boolean | undefined;
60
83
  }
61
84
 
62
- /** The CSV loss-note codes of check(); the shared ones are LOSS's. */
85
+ /**
86
+ * The CSV loss-note codes of check(); the shared ones are LOSS's.
87
+ * @category Built-in formats
88
+ */
63
89
  export const CSV_LOSS = Object.freeze({
64
- /** Two node ids share one text (a number and a string); export() throws E_INVALID_ID. */
90
+ /**
91
+ * Two node ids would be written as the same text (the number 5 and the text "5"); the save fails with
92
+ * E_INVALID_ID.
93
+ */
65
94
  ID_TEXT_COLLISION: LOSS.ID_TEXT_COLLISION,
66
- /** Ids whose text reads back as the other type under the canonical rule. */
95
+ /** Ids that read back as a different type, such as the text "7" as the number 7. */
67
96
  ID_TEXT_TYPE: LOSS.ID_TEXT_TYPE,
68
97
  /**
69
98
  * The generic dialect has no direction column; an undirected or mixed graph reads back as
@@ -75,29 +104,54 @@ export const CSV_LOSS = Object.freeze({
75
104
  MUTUAL_EXPANDED: LOSS.MUTUAL_EXPANDED,
76
105
  /** An attribute column named like a reserved header is not written. */
77
106
  RESERVED_NAME: "W_CSV_RESERVED_NAME",
78
- /** A column without a role that the importer gives one back by its name. */
107
+ /**
108
+ * An attribute without a role is written where the format keeps a role (for example, a `name` column as the label), and
109
+ * reads back with that role.
110
+ */
79
111
  ROLE_ASSUMED: LOSS.ROLE_ASSUMED,
80
- /** A role column (id, label) whose name the importer does not recognise; the role is lost. */
112
+ /** A role column (id, label) whose name the importer does not recognize; the role is lost. */
81
113
  ROLE_NAME: "W_CSV_ROLE_NAME",
82
- /** A role column (id, label) that is not string / dict reads back as string. */
114
+ /** An id or label attribute that is not text reads back as text. */
83
115
  TEXT_ROLE: "W_CSV_TEXT_ROLE",
84
116
  /** NaN / Infinity in a numeric column read back as text. */
85
117
  NONFINITE: "W_CSV_NONFINITE",
86
- /** A text column whose every value reads back as a number or boolean. */
118
+ /**
119
+ * A text value that reads back as a number or a boolean, because the format does not record that it was text (the
120
+ * text "42" reads back as the number 42).
121
+ */
87
122
  TEXT_INFERRED: LOSS.TEXT_INFERRED,
88
- /** A dict column whose cardinality makes the importer read it back as string, or the reverse. */
123
+ /**
124
+ * A text attribute reads back as a dictionary attribute, or the reverse, because the importer chooses by how often
125
+ * its values repeat. The values are the same.
126
+ */
89
127
  STORAGE_CLASS_CHANGED: LOSS.STORAGE_CLASS,
90
128
  /** Node attributes are written by a `table: "nodes"` export only. */
91
129
  NODE_TABLE: "W_CSV_NODE_TABLE",
92
- /** The edge table carries no node without an edge: isolated nodes vanish on re-import. */
130
+ /**
131
+ * The edge table has no row for a node without edges, so isolated nodes are missing when the file is read back.
132
+ * Write the node table too (`table: "nodes"`).
133
+ */
93
134
  ISOLATED_NODES: "W_CSV_ISOLATED_NODES",
94
- /** The edge table lists nodes by first appearance; the node order (and indices) change on re-import. */
135
+ /**
136
+ * The edge table lists nodes in the order they first appear in an edge, so the node order changes when the file is
137
+ * read back.
138
+ */
95
139
  NODE_ORDER: "W_CSV_NODE_ORDER",
96
140
  /** An adjacency table holds no edge column but the weight: edge ids, labels and attributes are not written. */
97
141
  EDGE_COLUMNS: "W_CSV_EDGE_COLUMNS",
142
+ /**
143
+ * `header: false` with columns a file without a header cannot name: graph-io reads such a file by position
144
+ * (source, target, weight, then columns it names column4, column5, ...), so these columns read back under other
145
+ * names or in the wrong place (for example, an edge id in the weight's place). Write the header, or write only source,
146
+ * target and weight with `dialect: "generic"`.
147
+ */
148
+ HEADERLESS: "W_CSV_HEADERLESS",
98
149
  });
99
150
 
100
- /** What the CSV format keeps as declared. */
151
+ /**
152
+ * What the CSV format keeps as declared.
153
+ * @category Built-in formats
154
+ */
101
155
  export const CSV_CAPABILITIES: ExportCapabilities = capabilities({
102
156
  mixedDirection: true,
103
157
  multiEdges: true,
@@ -190,7 +244,12 @@ function resolveCsvExportOptions(
190
244
  options: (CsvExportOptions & CommonExportOptions) | undefined,
191
245
  ): ResolvedCsvExportOptions {
192
246
  const o: CsvExportOptions = options ?? {};
193
- if (o.dialect !== undefined && o.dialect !== "gephi" && o.dialect !== "generic") {
247
+ if (
248
+ o.dialect !== undefined &&
249
+ o.dialect !== "gephi" &&
250
+ o.dialect !== "generic" &&
251
+ !otherFormatDialect("csv", o.dialect)
252
+ ) {
194
253
  throw new GraphFormatError("E_UNSUPPORTED", 'option dialect: expected "gephi" or "generic"', {
195
254
  option: "dialect",
196
255
  found: o.dialect,
@@ -235,7 +294,8 @@ function resolveCsvExportOptions(
235
294
  });
236
295
  }
237
296
  return {
238
- dialect: DIALECTS[o.dialect ?? "gephi"],
297
+ // another format's dialect (a JSON "d3" in a shared options object) leaves CSV's default
298
+ dialect: DIALECTS[o.dialect === "generic" ? "generic" : "gephi"],
239
299
  table: o.table ?? "edges",
240
300
  delimiter: o.delimiter ?? ",",
241
301
  newline: o.newline ?? "\n",
@@ -321,6 +381,33 @@ function cellText(column: Column, row: number): string | null {
321
381
  * @param values - whether to scan the values for notes
322
382
  * @returns the plan
323
383
  */
384
+ /**
385
+ * W_CSV_NODE_TABLE: the node columns an edge-table or adjacency export leaves for a second, node-table export.
386
+ * @param names - the node columns, label first
387
+ * @param table - the table being written ("edges" or "adjacency")
388
+ * @param note - the recorder
389
+ */
390
+ function nodeTableNote(
391
+ names: readonly string[],
392
+ table: string,
393
+ note: (code: string, message: string, column?: string | null, count?: number | null) => void,
394
+ ): void {
395
+ const written = names.length;
396
+ if (written > 0) {
397
+ const shown =
398
+ names
399
+ .slice(0, 3)
400
+ .map((n) => JSON.stringify(n))
401
+ .join(", ") + (written > 3 ? ", ..." : "");
402
+ note(
403
+ CSV_LOSS.NODE_TABLE,
404
+ `the ${table === "adjacency" ? "adjacency" : "edge"} table has no room for node attributes: ${written} node column${plural(written)} (${shown}) ${agree(written, "is", "are")} written only by a second export with table: "nodes"`,
405
+ null,
406
+ written,
407
+ );
408
+ }
409
+ }
410
+
324
411
  /**
325
412
  * The id notes: text collisions are fatal (export() throws E_INVALID_ID); type changes under the
326
413
  * canonical re-read are reported.
@@ -348,7 +435,7 @@ function idNotes(
348
435
  if (collisions > 0) {
349
436
  note(
350
437
  CSV_LOSS.ID_TEXT_COLLISION,
351
- `${collisions} node id(s) share their text with another id (a number and a string); export() will throw E_INVALID_ID`,
438
+ `${collisions} node id${plural(collisions)} ${agree(collisions, "shares", "share")} their text with another id (a number and a string); the save fails with E_INVALID_ID`,
352
439
  null,
353
440
  collisions,
354
441
  );
@@ -365,7 +452,7 @@ function idNotes(
365
452
  if (changed > 0) {
366
453
  note(
367
454
  CSV_LOSS.ID_TEXT_TYPE,
368
- `${changed} node id(s) read back as the other type under ids: "canonical" (a string "1" becomes 1, a number 1.5 becomes "1.5")`,
455
+ `${changed} node id${plural(changed)} ${agree(changed, "reads", "read")} back as the other type under ids: "canonical" (a string "1" becomes 1, a number 1.5 becomes "1.5")`,
369
456
  null,
370
457
  changed,
371
458
  );
@@ -402,14 +489,14 @@ function planExport(
402
489
  if (!snapshot.directed) {
403
490
  note(
404
491
  CSV_LOSS.DIRECTION_DROPPED,
405
- `${where} has no direction column; ${snapshot.edgeCount} undirected edge(s) read back as directed unless the importer is told otherwise`,
492
+ `${where} has no direction column; ${snapshot.edgeCount} undirected edge${plural(snapshot.edgeCount)} ${agree(snapshot.edgeCount, "reads", "read")} back as directed unless the importer is told otherwise`,
406
493
  null,
407
494
  snapshot.edgeCount,
408
495
  );
409
496
  } else if (mixed > 0) {
410
497
  note(
411
498
  CSV_LOSS.DIRECTION_DROPPED,
412
- `${where} has no direction column; ${mixed} undirected edge(s) of a mixed graph read back as one directed edge each`,
499
+ `${where} has no direction column; ${mixed} undirected edge${plural(mixed)} of a mixed graph read back as one directed edge each`,
413
500
  null,
414
501
  mixed,
415
502
  );
@@ -425,7 +512,7 @@ function planExport(
425
512
  if (folding.mutualCount > 0) {
426
513
  note(
427
514
  CSV_LOSS.MUTUAL_EXPANDED,
428
- `${folding.mutualCount} mutual pair(s) are written as two directed rows; the mutual mark is lost`,
515
+ `${folding.mutualCount} mutual pair${plural(folding.mutualCount)} ${agree(folding.mutualCount, "is", "are")} written as two directed rows; the mutual mark is lost`,
429
516
  null,
430
517
  folding.mutualCount,
431
518
  );
@@ -457,7 +544,7 @@ function planExport(
457
544
  if (dropped > 0) {
458
545
  note(
459
546
  CSV_LOSS.EDGE_COLUMNS,
460
- `${dropped} edge column(s) are not written: an adjacency table holds the weight only`,
547
+ `${dropped} edge column${plural(dropped)} ${agree(dropped, "is", "are")} not written: an adjacency table holds the weight only`,
461
548
  null,
462
549
  dropped,
463
550
  );
@@ -496,15 +583,11 @@ function planExport(
496
583
  }
497
584
  }
498
585
  } else {
499
- const written = nodeColumns.length + (nodeLabel === null ? 0 : 1);
500
- if (written > 0) {
501
- note(
502
- CSV_LOSS.NODE_TABLE,
503
- `${written} node column(s) are written by a table: "nodes" export only`,
504
- null,
505
- written,
506
- );
507
- }
586
+ nodeTableNote(
587
+ [...(nodeLabel === null ? [] : [nodeLabel.meta.name]), ...nodeColumns.map((c) => c.column.meta.name)],
588
+ csv.table,
589
+ note,
590
+ );
508
591
  }
509
592
 
510
593
  return {
@@ -563,7 +646,7 @@ function noteNodeCoverage(
563
646
  if (isolated > 0) {
564
647
  note(
565
648
  CSV_LOSS.ISOLATED_NODES,
566
- `${isolated} node(s) have no edge and cannot be written by the edge table; write the node table (table: "nodes") to keep them`,
649
+ `${isolated} node${plural(isolated)} ${agree(isolated, "has", "have")} no edge and cannot be written by the edge table; write the node table (table: "nodes") to keep them`,
567
650
  null,
568
651
  isolated,
569
652
  );
@@ -571,7 +654,7 @@ function noteNodeCoverage(
571
654
  if (reordered > 0) {
572
655
  note(
573
656
  CSV_LOSS.NODE_ORDER,
574
- `${reordered} node(s) are first mentioned by an edge row out of index order; a re-import numbers nodes by first appearance`,
657
+ `${reordered} node${plural(reordered)} ${agree(reordered, "is", "are")} first mentioned by an edge row out of index order; a re-import numbers nodes by first appearance`,
575
658
  null,
576
659
  reordered,
577
660
  );
@@ -746,7 +829,12 @@ function checkValues(
746
829
  }
747
830
  }
748
831
  if (nonFinite > 0) {
749
- note(CSV_LOSS.NONFINITE, `${label}: ${nonFinite} non-finite value(s) read back as text`, name, nonFinite);
832
+ note(
833
+ CSV_LOSS.NONFINITE,
834
+ `${label}: ${nonFinite} non-finite value${plural(nonFinite)} ${agree(nonFinite, "reads", "read")} back as text`,
835
+ name,
836
+ nonFinite,
837
+ );
750
838
  }
751
839
  return;
752
840
  }
@@ -810,10 +898,10 @@ function typeText(snapshot: GraphSnapshot, plan: Plan, e: number): string {
810
898
  }
811
899
 
812
900
  /**
813
- * A neighbour cell of the adjacency table: `id:weight` for an explicit weight; `id:` for an id
901
+ * A neighbor cell of the adjacency table: `id:weight` for an explicit weight; `id:` for an id
814
902
  * holding a colon without one, so the importer does not read the id's tail as a weight; `id`
815
903
  * otherwise.
816
- * @param id - the neighbour's id text
904
+ * @param id - the neighbor's id text
817
905
  * @param weight - the weight text, or null
818
906
  * @returns the cell text (unquoted)
819
907
  */
@@ -1006,6 +1094,68 @@ function prepare(snapshot: GraphSnapshot, options: (CsvExportOptions & CommonExp
1006
1094
  return plan;
1007
1095
  }
1008
1096
 
1097
+ /**
1098
+ * The note of a table written without its header: a headerless file is read by position (source, target, weight,
1099
+ * then unnamed columns; a node table: id, then unnamed columns), so any other column reads back elsewhere or unnamed.
1100
+ * @param plan - the export plan
1101
+ * @returns the note, or nothing when the header is written or the positions match
1102
+ */
1103
+ function headerlessNotes(plan: Plan): LossNote[] {
1104
+ const { csv } = plan;
1105
+ if (csv.header || csv.table === "adjacency") {
1106
+ return [];
1107
+ }
1108
+ const names = csv.table === "nodes" ? headerlessNodeColumns(plan) : headerlessEdgeColumns(plan);
1109
+ if (names.length === 0) {
1110
+ return [];
1111
+ }
1112
+ const shown = names.map((n) => JSON.stringify(n)).join(", ");
1113
+ return [
1114
+ Object.freeze({
1115
+ code: CSV_LOSS.HEADERLESS,
1116
+ message: `without a header the file is read back by position (${csv.table === "nodes" ? "id" : "source, target, weight"}, then unnamed columns), so ${names.length === 1 ? "the column" : "the columns"} ${shown} ${agree(names.length, "reads", "read")} back unnamed or in another column's place; write the header, or for an edge list pass dialect: "generic" and write only source, target and weight`,
1117
+ column: null,
1118
+ count: names.length,
1119
+ }),
1120
+ ];
1121
+ }
1122
+
1123
+ /**
1124
+ * The node columns a headerless node table does not read back by position: every one after the id.
1125
+ * @param plan - the export plan
1126
+ * @returns their names
1127
+ */
1128
+ function headerlessNodeColumns(plan: Plan): string[] {
1129
+ const label = plan.nodeLabel === null ? [] : [plan.nodeLabel.meta.name];
1130
+ return [...label, ...plan.nodeColumns.map((c) => c.header)];
1131
+ }
1132
+
1133
+ /**
1134
+ * The edge columns a headerless edge list does not read back by position: every one after the
1135
+ * endpoints and the weight, and the weight when another column comes before it.
1136
+ * @param plan - the export plan
1137
+ * @returns their names
1138
+ */
1139
+ function headerlessEdgeColumns(plan: Plan): string[] {
1140
+ const { dialect } = plan.csv;
1141
+ const names: string[] = [];
1142
+ if (dialect.type !== null) {
1143
+ names.push(dialect.type);
1144
+ }
1145
+ if (plan.edgeId !== null) {
1146
+ names.push(plan.edgeId.meta.name);
1147
+ }
1148
+ if (plan.edgeLabel !== null) {
1149
+ names.push(plan.edgeLabel.meta.name);
1150
+ }
1151
+ // a weight right after the target is where a headerless read expects it
1152
+ if (plan.weights.weighted && names.length > 0) {
1153
+ names.push(dialect.weight);
1154
+ }
1155
+ names.push(...plan.edgeColumns.map((c) => c.header));
1156
+ return names;
1157
+ }
1158
+
1009
1159
  /**
1010
1160
  * Pre-flight: what a CSV export would lose. The generic notes describe the snapshot as a whole
1011
1161
  * against the format; the CSV notes concern the table selected by `table`.
@@ -1018,12 +1168,17 @@ function check(snapshot: GraphSnapshot, options?: CsvExportOptions & CommonExpor
1018
1168
  return Object.freeze([
1019
1169
  ...checkCapabilities(snapshot, CSV_CAPABILITIES, plan.common, { roles: KEPT_ROLES }),
1020
1170
  ...plan.notes,
1171
+ ...headerlessNotes(plan),
1021
1172
  ]);
1022
1173
  }
1023
1174
 
1024
- /** The CSV / TSV exporter plugin (subpath `@graphty/graph-io/csv`). */
1175
+ /**
1176
+ * The CSV / TSV exporter plugin (subpath `@graphty/graph-io/csv`).
1177
+ * @category Built-in formats
1178
+ */
1025
1179
  export const csvExporter: GraphExporter<CsvExportOptions> = Object.freeze({
1026
1180
  format: "csv",
1181
+ options: Object.freeze(["delimiter", "dialect", "header", "newline", "table"]),
1027
1182
  capabilities: CSV_CAPABILITIES,
1028
1183
  check,
1029
1184
  export(snapshot: GraphSnapshot, options?: CsvExportOptions & CommonExportOptions): AsyncIterable<Uint8Array> {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Header handling of the CSV importer: whether the first row is a header, which columns hold the
3
3
  * endpoints, the weight, the Gephi per-row `Type`, the edge id and the label (by name lists and
4
- * by position), and the synthesised names of a headerless file (`column1`, `column2`, ...).
4
+ * by position), and the synthesized names of a headerless file (`column1`, `column2`, ...).
5
5
  *
6
6
  * Name resolution is exact first, then case-insensitive, over a candidate list in priority order,
7
7
  * so `source` / `Source` / `SOURCE`, `src`, `from` all resolve without configuration; the Gephi
@@ -11,12 +11,19 @@
11
11
 
12
12
  import { GraphFormatError } from "@graphty/graph-format";
13
13
 
14
+ import { plural } from "../../common/plural.js";
14
15
  import { inferTextDtype } from "../../common/text.js";
15
16
 
16
- /** A column named by header text or by 0-based position. */
17
+ /**
18
+ * A column named by header text or by 0-based position.
19
+ * @category Built-in formats
20
+ */
17
21
  export type CsvColumnRef = string | number;
18
22
 
19
- /** Header candidates of the source endpoint, in priority order (matched exactly, then case-insensitively). */
23
+ /**
24
+ * Header candidates of the source endpoint, in priority order (matched exactly, then case-insensitively).
25
+ * @category Plugin helpers
26
+ */
20
27
  export const SOURCE_NAMES: readonly string[] = Object.freeze([
21
28
  "source",
22
29
  "src",
@@ -29,7 +36,10 @@ export const SOURCE_NAMES: readonly string[] = Object.freeze([
29
36
  ":start_id",
30
37
  ]);
31
38
 
32
- /** Header candidates of the target endpoint. */
39
+ /**
40
+ * Header candidates of the target endpoint.
41
+ * @category Plugin helpers
42
+ */
33
43
  export const TARGET_NAMES: readonly string[] = Object.freeze([
34
44
  "target",
35
45
  "dst",
@@ -43,16 +53,28 @@ export const TARGET_NAMES: readonly string[] = Object.freeze([
43
53
  ":end_id",
44
54
  ]);
45
55
 
46
- /** Header candidates of a node table's id column. */
56
+ /**
57
+ * Header candidates of a node table's id column.
58
+ * @category Plugin helpers
59
+ */
47
60
  export const ID_NAMES: readonly string[] = Object.freeze(["id", "node", "name", "key"]);
48
61
 
49
- /** Header candidates of a label column (node or edge). */
62
+ /**
63
+ * Header candidates of a label column (node or edge).
64
+ * @category Plugin helpers
65
+ */
50
66
  export const LABEL_NAMES: readonly string[] = Object.freeze(["label"]);
51
67
 
52
- /** Header candidates of an edge id column. */
68
+ /**
69
+ * Header candidates of an edge id column.
70
+ * @category Plugin helpers
71
+ */
53
72
  export const EDGE_ID_NAMES: readonly string[] = Object.freeze(["id"]);
54
73
 
55
- /** The Gephi per-row direction column. */
74
+ /**
75
+ * The Gephi per-row direction column.
76
+ * @category Plugin helpers
77
+ */
56
78
  export const TYPE_NAME = "Type";
57
79
 
58
80
  /** Every name that marks a first row as a header when the caller leaves detection to the importer. */
@@ -72,6 +94,7 @@ const HEADER_MARKERS: ReadonlySet<string> = new Set([
72
94
  * @param names - the header names
73
95
  * @param candidates - the names to look for, in priority order
74
96
  * @returns the column index, or -1
97
+ * @category Plugin helpers
75
98
  */
76
99
  export function findColumn(names: readonly string[], candidates: readonly string[]): number {
77
100
  for (const candidate of candidates) {
@@ -96,13 +119,14 @@ export function findColumn(names: readonly string[], candidates: readonly string
96
119
  * @param ref - the option value
97
120
  * @param option - the option name, for the error
98
121
  * @returns the column index
122
+ * @category Plugin helpers
99
123
  */
100
124
  export function resolveColumnRef(names: readonly string[], ref: CsvColumnRef, option: string): number {
101
125
  if (typeof ref === "number") {
102
126
  if (!Number.isInteger(ref) || ref < 0 || ref >= names.length) {
103
127
  throw new GraphFormatError(
104
128
  "E_UNSUPPORTED",
105
- `option ${option}: column ${ref} does not exist (the file has ${names.length} column(s))`,
129
+ `option ${option}: column ${ref} does not exist (the file has ${names.length} column${plural(names.length)})`,
106
130
  { option, found: ref, columns: names.length },
107
131
  );
108
132
  }
@@ -124,21 +148,34 @@ export function resolveColumnRef(names: readonly string[], ref: CsvColumnRef, op
124
148
  * is when any cell is a known column name (source, target, id, label, weight, type...), or when
125
149
  * every cell is non-numeric text while the second row has a numeric cell (`u,v` over `1,2`);
126
150
  * a first row with a numeric cell is data, and so is one that looks exactly like the rows below it.
151
+ * A two-column row holding a known name is still data when its second cell is the second row's
152
+ * first cell and it does not name both endpoints: a header names columns, while an edge list whose
153
+ * ids happen to be such words (`key,lock` over `lock,door`) chains its ids from row to row.
127
154
  * @param first - the first row
128
155
  * @param second - the second row, or null when the file has one row
129
156
  * @returns true when the first row is a header
157
+ * @category Plugin helpers
130
158
  */
131
159
  export function looksLikeHeader(first: readonly string[], second: readonly string[] | null): boolean {
132
160
  let allText = true;
161
+ let marker = false;
133
162
  for (const cell of first) {
134
163
  const text = cell.trim();
135
164
  if (HEADER_MARKERS.has(text.toLowerCase())) {
136
- return true;
165
+ marker = true;
137
166
  }
138
167
  if (text.length === 0 || inferTextDtype(text) !== "string") {
139
168
  allText = false;
140
169
  }
141
170
  }
171
+ if (marker) {
172
+ const names = headerNames(first);
173
+ if (second === null || (findColumn(names, SOURCE_NAMES) >= 0 && findColumn(names, TARGET_NAMES) >= 0)) {
174
+ return true;
175
+ }
176
+ const chained = first.length === 2 && second.length >= 1 && first[1].trim() === second[0].trim();
177
+ return !chained || first[1].trim().length === 0;
178
+ }
142
179
  if (!allText || second === null) {
143
180
  return false;
144
181
  }
@@ -146,9 +183,10 @@ export function looksLikeHeader(first: readonly string[], second: readonly strin
146
183
  }
147
184
 
148
185
  /**
149
- * The synthesised header of a headerless file: `column1` ... `columnN`.
186
+ * The synthesized header of a headerless file: `column1` ... `columnN`.
150
187
  * @param width - the number of cells of the first row
151
188
  * @returns the names
189
+ * @category Plugin helpers
152
190
  */
153
191
  export function positionalNames(width: number): string[] {
154
192
  const names: string[] = [];
@@ -163,6 +201,7 @@ export function positionalNames(width: number): string[] {
163
201
  * empty cell named by its position so every column has a name.
164
202
  * @param cells - the header row
165
203
  * @returns the names
204
+ * @category Plugin helpers
166
205
  */
167
206
  export function headerNames(cells: readonly string[]): string[] {
168
207
  return cells.map((cell, i) => {