@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
@@ -1,7 +1,9 @@
1
1
  /**
2
- * The `@graphty/graph-io/cys` subpath: the Cytoscape session importer, its option type and its
3
- * issue code table. Sessions are read-only: graph-io writes XGMML and CX2, which Cytoscape opens.
2
+ * The `@graphty/graph-io/cys` subpath: the Cytoscape session importer and exporter, their option
3
+ * types and their issue and loss code tables.
4
+ * @module @graphty/graph-io/cys
4
5
  */
5
6
 
6
7
  export { CYS_ISSUE } from "./constants.js";
8
+ export { CYS_CAPABILITIES, CYS_LOSS, cysExporter, type CysExportOptions } from "./exporter.js";
7
9
  export { cysImporter, type CysImportOptions } from "./importer.js";
@@ -8,13 +8,17 @@
8
8
 
9
9
  import { readBytes, textChunks } from "../../common/input.js";
10
10
  import { type ResolvedImportOptions } from "../../common/options.js";
11
+ import { plural } from "../../common/plural.js";
11
12
  import { ImportReportBuilder } from "../../common/report.js";
12
13
  import { tokenizeXml, xmlDeclaredEncoding, XmlSyntaxError } from "../../common/xml.js";
13
14
  import { readZipDirectory, readZipEntry, type ZipEntry, ZipError } from "../../common/zip.js";
14
15
  import { ImportError, type ImportInput } from "../../types.js";
15
16
  import { CYS_ISSUE, FORMAT, MAX_RATIO } from "./constants.js";
16
17
 
17
- /** An entry of the session, by its path under the session's root folder. */
18
+ /**
19
+ * An entry of the session, by its path under the session's root folder.
20
+ * @category Plugin helpers
21
+ */
18
22
  export interface SessionEntry {
19
23
  /** The path under the root folder, as the archive spells it (URL-encoded parts). */
20
24
  readonly path: string;
@@ -24,7 +28,10 @@ export interface SessionEntry {
24
28
  readonly zip: ZipEntry;
25
29
  }
26
30
 
27
- /** A 3.x network file: one root network (a collection). */
31
+ /**
32
+ * A 3.x network file: one root network (a collection).
33
+ * @category Plugin helpers
34
+ */
28
35
  export interface NetworkEntry extends SessionEntry {
29
36
  /** The root network's saved SUID. */
30
37
  readonly suid: string;
@@ -40,7 +47,10 @@ interface ViewEntry extends SessionEntry {
40
47
  readonly view: string;
41
48
  }
42
49
 
43
- /** A 3.x table file. */
50
+ /**
51
+ * A 3.x table file.
52
+ * @category Plugin helpers
53
+ */
44
54
  export interface TableEntry extends SessionEntry {
45
55
  /** The path under `tables/` (what `cytables.xml` names). */
46
56
  readonly tablePath: string;
@@ -77,15 +87,22 @@ interface SessionLayout {
77
87
  readonly skipped: readonly string[];
78
88
  }
79
89
 
80
- /** An opened session: its bytes, its layout and an entry reader within the byte budget. */
90
+ /**
91
+ * An opened session: its bytes, its layout and an entry reader within the byte budget.
92
+ * @category Plugin helpers
93
+ */
81
94
  export interface Session {
82
95
  readonly layout: SessionLayout;
83
96
  /**
84
- * Inflate one entry.
97
+ * Inflate one entry. Each entry counts against the byte budget and the progress once, however
98
+ * often it is read.
85
99
  * @param entry - the entry
100
+ * @param report - the report a damaged or over-budget entry fails (the network being imported)
86
101
  * @returns its bytes
87
102
  */
88
- read(entry: SessionEntry): Promise<Uint8Array>;
103
+ read(entry: SessionEntry, report: ImportReportBuilder): Promise<Uint8Array>;
104
+ /** Report the progress complete: the import has read everything it needs. */
105
+ done(): void;
89
106
  }
90
107
 
91
108
  /**
@@ -93,6 +110,7 @@ export interface Session {
93
110
  * text as it is.
94
111
  * @param text - the encoded text
95
112
  * @returns the decoded text
113
+ * @category Plugin helpers
96
114
  */
97
115
  export function urlDecode(text: string): string {
98
116
  const plus = text.replace(/\+/g, " ");
@@ -139,25 +157,40 @@ export async function openSession(
139
157
  const layout = layoutOf(zipEntries, report);
140
158
  let budget = maxBytes;
141
159
  let inflated = 0;
142
- const total = zipEntries.reduce((sum, e) => sum + e.size, 0);
160
+ // the progress total: the entries the importer may read, not images and app files
161
+ const total = [
162
+ ...layout.networks,
163
+ ...layout.views,
164
+ ...layout.tables,
165
+ ...layout.files.values(),
166
+ ...[layout.cytables, layout.networkList, layout.cysession].filter((e) => e !== null),
167
+ ].reduce((sum, e) => sum + e.zip.size, 0);
168
+ const charged = new Set<string>();
143
169
  return {
144
170
  layout,
145
- read: async (entry: SessionEntry): Promise<Uint8Array> => {
171
+ read: async (entry: SessionEntry, into: ImportReportBuilder): Promise<Uint8Array> => {
172
+ const first = !charged.has(entry.name);
146
173
  const before = inflated;
147
174
  try {
148
175
  const data = await readZipEntry(bytes, entry.zip, {
149
176
  signal: common.signal,
150
- maxBytes: budget,
177
+ maxBytes: first ? budget : entry.zip.size,
151
178
  maxRatio: MAX_RATIO,
152
- onBytes: (n) => common.onProgress?.(before + n, total),
179
+ onBytes: first ? (n): void => common.onProgress?.(Math.min(before + n, total), total) : undefined,
153
180
  });
154
- budget -= data.byteLength;
155
- inflated += data.byteLength;
181
+ if (first) {
182
+ charged.add(entry.name);
183
+ budget -= data.byteLength;
184
+ inflated += data.byteLength;
185
+ }
156
186
  return data;
157
187
  } catch (err) {
158
- return zipFailure(err, report);
188
+ return zipFailure(err, into);
159
189
  }
160
190
  },
191
+ done: (): void => {
192
+ common.onProgress?.(total, total);
193
+ },
161
194
  };
162
195
  }
163
196
 
@@ -184,6 +217,20 @@ function zipFailure(err: unknown, report: ImportReportBuilder): never {
184
217
  report.fail(code, err.message);
185
218
  }
186
219
 
220
+ /**
221
+ * The session marker of the archive: the shallowest entry whose name ends in `.version` (a
222
+ * session re-zipped inside another folder keeps its layout one level down), else null.
223
+ * @param names - the entry names
224
+ * @param suffix - the marker's file name pattern
225
+ * @returns the names of the shallowest such entries, in directory order
226
+ */
227
+ function shallowest(names: readonly string[], suffix: RegExp): string[] {
228
+ const depth = (name: string): number => name.split("/").length;
229
+ const found = names.filter((n) => suffix.test(n));
230
+ const least = Math.min(...found.map(depth));
231
+ return found.filter((n) => depth(n) === least);
232
+ }
233
+
187
234
  /** A 3.x network entry name: `<SUID>[-<name>].xgmml`. */
188
235
  const NETWORK_FILE = /^networks\/(\d+)(?:-([^/]*))?\.xgmml$/;
189
236
  /** A 3.x view entry name: `<networkSUID>-<viewSUID>[-<title>].xgmml`. */
@@ -206,25 +253,35 @@ function layoutOf(zipEntries: readonly ZipEntry[], report: ImportReportBuilder):
206
253
  const byName = new Map<string, ZipEntry>();
207
254
  const repeated: string[] = [];
208
255
  for (const entry of zipEntries) {
209
- if (entry.directory || NOISE.test(entry.name)) {
256
+ // a Windows tool may write backslashes, which APPNOTE 4.4.17 forbids: read them as "/"
257
+ const name = entry.name.replaceAll("\\", "/");
258
+ if (name.endsWith("/") || NOISE.test(name)) {
210
259
  continue;
211
260
  }
212
- if (byName.has(entry.name)) {
213
- repeated.push(entry.name);
261
+ if (byName.has(name)) {
262
+ repeated.push(name);
214
263
  continue;
215
264
  }
216
- byName.set(entry.name, entry);
265
+ byName.set(name, entry);
217
266
  }
218
267
  if (repeated.length > 0) {
219
268
  report.warning(
220
269
  "unsupported",
221
270
  CYS_ISSUE.DUPLICATE_ENTRY,
222
- `${repeated.length} entry name(s) appear more than once; the first of each is read: ${listed(repeated)}`,
271
+ `${repeated.length} entry name${plural(repeated.length)} appear more than once; the first of each is read: ${listed(repeated)}`,
223
272
  );
224
273
  }
225
274
  const names = [...byName.keys()];
226
- const marker = names.find((n) => /^([^/]*\/)?[^/]+\.version$/.test(n));
227
- const cysession = names.find((n) => /^([^/]*\/)?cysession\.xml$/.test(n));
275
+ const markers = shallowest(names, /(^|\/)[^/]+\.version$/);
276
+ const marker = markers.at(0);
277
+ const cysession = shallowest(names, /(^|\/)cysession\.xml$/).at(0);
278
+ if (markers.length > 1) {
279
+ report.warning(
280
+ "validation-error",
281
+ CYS_ISSUE.ENTRY_SKIPPED,
282
+ `the session has ${markers.length} version markers (${listed(markers)}); ${markers[0]} is used and the others are not read`,
283
+ );
284
+ }
228
285
  if (marker === undefined && cysession === undefined) {
229
286
  report.fail(
230
287
  CYS_ISSUE.NOT_SESSION,
@@ -237,8 +294,14 @@ function layoutOf(zipEntries: readonly ZipEntry[], report: ImportReportBuilder):
237
294
  let version = "2.0.0";
238
295
  if (marker !== undefined) {
239
296
  version = marker.slice(root.length, -".version".length);
297
+ if (!/^\d+(\.\d+)*$/.test(version)) {
298
+ report.fail(
299
+ CYS_ISSUE.VERSION,
300
+ `the session version marker ${marker} does not parse as a version (<major>.<minor>.<patch>.version)`,
301
+ );
302
+ }
240
303
  const major = Number(version.split(".")[0]);
241
- if (!Number.isInteger(major) || major > 3) {
304
+ if (major > 3) {
242
305
  report.fail(
243
306
  CYS_ISSUE.VERSION,
244
307
  `the session version ${version} is newer than the Cytoscape 3 sessions graph-io reads`,
@@ -262,7 +325,7 @@ function layoutOf(zipEntries: readonly ZipEntry[], report: ImportReportBuilder):
262
325
  };
263
326
  for (const [name, zip] of byName) {
264
327
  if (!name.startsWith(root) || name === marker) {
265
- if (name !== marker) {
328
+ if (name !== marker && !markers.includes(name)) {
266
329
  layout.skipped.push(name);
267
330
  }
268
331
  continue;
@@ -300,12 +363,17 @@ function classify3(entry: SessionEntry, layout: Mutable): void {
300
363
  "org.cytoscape.model.CyEdge": "edge",
301
364
  "org.cytoscape.model.CyNetwork": "network",
302
365
  }[urlDecode(table[4])] as TableEntry["element"] | undefined;
366
+ if (element === undefined) {
367
+ // a table of an element class graph-io has no model for
368
+ layout.skipped.push(entry.name);
369
+ return;
370
+ }
303
371
  layout.tables.push({
304
372
  ...entry,
305
373
  tablePath: table[1],
306
374
  network: table[2],
307
375
  namespace: urlDecode(table[3]),
308
- element: element ?? null,
376
+ element,
309
377
  });
310
378
  } else if (path === "apps/org.cytoscape.swing-application/network_list.xml") {
311
379
  layout.networkList = entry;
@@ -343,13 +411,27 @@ type Mutable = {
343
411
  * A list of names for a message: the first ten, then a count.
344
412
  * @param names - the names
345
413
  * @returns the text
414
+ * @category Plugin helpers
346
415
  */
347
416
  export function listed(names: readonly string[]): string {
348
- const head = names.slice(0, 10).join(", ");
417
+ const head = names.slice(0, 10).map(entryLabel).join(", ");
349
418
  return names.length > 10 ? `${head} and ${names.length - 10} more` : head;
350
419
  }
351
420
 
352
- /** One element of a small XML document, as a tree. */
421
+ /**
422
+ * An entry name as a message shows it: without the session folder every entry sits in
423
+ * (`CytoscapeSession-2026_10_02-12_00/networks/10-Collection.xgmml` is `networks/10-Collection.xgmml`).
424
+ * @param name - the zip entry name
425
+ * @returns the name inside the session
426
+ */
427
+ export function entryLabel(name: string): string {
428
+ return name.replace(/^[^/]*CytoscapeSession[^/]*\//, "");
429
+ }
430
+
431
+ /**
432
+ * One element of a small XML document, as a tree.
433
+ * @category Plugin helpers
434
+ */
353
435
  export interface XmlNode {
354
436
  /** The local name. */
355
437
  readonly name: string;
@@ -374,11 +456,30 @@ export async function readXmlTree(
374
456
  report: ImportReportBuilder,
375
457
  common: ResolvedImportOptions,
376
458
  ): Promise<XmlNode> {
459
+ const tree = await parseXmlTree(bytes, entry, report, common);
460
+ return typeof tree === "string" ? report.fail(CYS_ISSUE.CORRUPT, `${entry}: ${tree}`) : tree;
461
+ }
462
+
463
+ /**
464
+ * Read a small XML entry as a tree; its decoding warnings (W_ENCODING_FALLBACK,
465
+ * W_UNKNOWN_ENCODING) go into the report with the entry name.
466
+ * @param bytes - the entry's bytes
467
+ * @param entry - the entry name
468
+ * @param report - the report
469
+ * @param common - cancellation
470
+ * @returns the root element, or why the entry cannot be read
471
+ */
472
+ export async function parseXmlTree(
473
+ bytes: Uint8Array,
474
+ entry: string,
475
+ report: ImportReportBuilder,
476
+ common: ResolvedImportOptions,
477
+ ): Promise<XmlNode | string> {
377
478
  const scratch = new ImportReportBuilder(FORMAT, 0);
378
479
  const stack: XmlNode[] = [{ name: "", attrs: new Map(), children: [] }];
379
480
  try {
380
481
  await tokenizeXml(
381
- textChunks(bytes, scratch, { signal: common.signal, declaredEncoding: xmlDeclaredEncoding }),
482
+ textChunks(bytes, scratch, { signal: common.signal, declaredEncoding: xmlDeclaredEncoding, xml: true }),
382
483
  {
383
484
  start(name, attrs): void {
384
485
  const node: XmlNode = { name: name.slice(name.lastIndexOf(":") + 1), attrs, children: [] };
@@ -395,15 +496,21 @@ export async function readXmlTree(
395
496
  );
396
497
  } catch (err) {
397
498
  if (err instanceof XmlSyntaxError || err instanceof ImportError) {
398
- report.fail(CYS_ISSUE.CORRUPT, `${entry}: ${err.message}`);
499
+ return err.message;
399
500
  }
400
501
  throw err;
401
502
  }
402
- const [root] = stack[0].children;
403
- if (root === undefined) {
404
- report.fail(CYS_ISSUE.CORRUPT, `${entry}: the document is empty`);
503
+ // the decoder's warnings (an encoding fallback, an unknown declared encoding) name the entry
504
+ for (const issue of scratch.issues) {
505
+ if (issue.severity === "warning") {
506
+ report.warning(issue.category, issue.code, `${entry}: ${issue.message}`, {
507
+ line: issue.line,
508
+ element: entry,
509
+ });
510
+ }
405
511
  }
406
- return root;
512
+ const [root] = stack[0].children;
513
+ return root ?? "the document is empty";
407
514
  }
408
515
 
409
516
  /**
@@ -411,6 +518,7 @@ export async function readXmlTree(
411
518
  * @param node - the tree
412
519
  * @param name - the local name
413
520
  * @returns the elements
521
+ * @category Plugin helpers
414
522
  */
415
523
  export function elementsNamed(node: XmlNode, name: string): XmlNode[] {
416
524
  const out: XmlNode[] = [];
@@ -7,11 +7,13 @@
7
7
  */
8
8
 
9
9
  import { type ResolvedImportOptions } from "../../common/options.js";
10
+ import { plural } from "../../common/plural.js";
10
11
  import { ImportReportBuilder } from "../../common/report.js";
11
12
  import { ImportError } from "../../types.js";
12
13
  import { CsvRecordReader } from "../csv/records.js";
13
14
  import { type AttRec } from "../xgmml/document.js";
14
15
  import { CYS_ISSUE, FORMAT } from "./constants.js";
16
+ import { entryLabel } from "./session.js";
15
17
 
16
18
  /** The Cytoscape type names of the Java classes a CyCSV column can hold. */
17
19
  const JAVA_TYPES: Readonly<Record<string, string>> = {
@@ -35,7 +37,10 @@ interface CyColumn {
35
37
  readonly list: boolean;
36
38
  }
37
39
 
38
- /** One table, read. */
40
+ /**
41
+ * One table, read.
42
+ * @category Plugin helpers
43
+ */
39
44
  export interface CyTable {
40
45
  /** The table's path under `tables/` as the archive spells it (what cytables.xml names). */
41
46
  readonly path: string;
@@ -89,22 +94,40 @@ export async function readCyTable(
89
94
  }
90
95
  let at = 0;
91
96
  let version = 0;
92
- if (records[0]?.cells.length === 2 && records[0].cells[0] === "CyCSV-Version") {
93
- version = Number(records[0].cells[1]);
97
+ if (records[0]?.cells[0] === "CyCSV-Version") {
98
+ const { cells } = records[0];
99
+ if (cells.length !== 2 || !/^\d+$/.test(cells[1].trim())) {
100
+ return tableError(report, entry, `the version row ${JSON.stringify(cells)} does not parse`);
101
+ }
102
+ version = Number(cells[1]);
94
103
  at = 1;
95
104
  }
96
105
  if (version !== 0 && version !== 1) {
97
106
  return tableError(report, entry, `CyCSV version "${records[0].cells[1]}" is not 0 or 1`);
98
107
  }
99
108
  // version 1: names, types, column options, table title; version 0: names, types, table title
100
- const headerLines = version === 1 ? 4 : 3;
101
- if (records.length < at + headerLines) {
109
+ let headerLines = version === 1 ? 4 : 3;
110
+ if (records.length < at + headerLines - 1) {
102
111
  return tableError(report, entry, "the table header is incomplete");
103
112
  }
113
+ // the reader skips blank lines, so a blank title line (another tool's) shows only as a gap
114
+ // in the line numbers: the record after the row before the title is then the first data row
115
+ const beforeTitle = records[at + headerLines - 2];
116
+ const title = records.at(at + headerLines - 1);
117
+ if (
118
+ title === undefined ||
119
+ (title.line > beforeTitle.line + 1 && !beforeTitle.cells.some((c) => /[\r\n]/.test(c)))
120
+ ) {
121
+ headerLines--;
122
+ }
104
123
  const names = records[at].cells;
105
124
  const classes = records[at + 1].cells;
106
125
  if (names.length === 0 || classes.length !== names.length) {
107
- return tableError(report, entry, `${names.length} column name(s) but ${classes.length} column class(es)`);
126
+ return tableError(
127
+ report,
128
+ entry,
129
+ `${names.length} column name${plural(names.length)} but ${classes.length} column class(es)`,
130
+ );
108
131
  }
109
132
  const columns: CyColumn[] = [];
110
133
  for (let i = 0; i < names.length; i++) {
@@ -140,7 +163,7 @@ export async function readCyTable(
140
163
  report.warning(
141
164
  "parse-error",
142
165
  CYS_ISSUE.TABLE_ROW,
143
- `${entry}: ${problems.short} row(s) with too few cells (the rest are unset), ${problems.long} with too many (the extra cells are ignored), ${problems.repeated} repeating a key (the first row is read)`,
166
+ `${entryLabel(entry)}: ${problems.short} row${plural(problems.short)} with too few cells (the rest are unset), ${problems.long} with too many (the extra cells are ignored), ${problems.repeated} repeating a key (the first row is read)`,
144
167
  );
145
168
  }
146
169
  return { path, entry, columns, rows, lines };
@@ -170,7 +193,7 @@ function columnOf(name: string, javaClass: string): CyColumn | null {
170
193
  * @returns null
171
194
  */
172
195
  function tableError(report: ImportReportBuilder, entry: string, reason: string): null {
173
- report.error("parse-error", CYS_ISSUE.TABLE, `${entry}: ${reason}; the table is not read`);
196
+ report.error("parse-error", CYS_ISSUE.TABLE, `${entryLabel(entry)}: ${reason}; the table is not read`);
174
197
  return null;
175
198
  }
176
199
 
@@ -185,6 +208,7 @@ function tableError(report: ImportReportBuilder, entry: string, reason: string):
185
208
  * @param namespace - the table namespace the column belongs to (null for the network's own table)
186
209
  * @param hidden - whether the column is hidden (HIDDEN and app tables)
187
210
  * @returns the att, or null
211
+ * @category Plugin helpers
188
212
  */
189
213
  export function cellAtt(
190
214
  column: CyColumn,
@@ -272,7 +296,10 @@ function att(
272
296
  };
273
297
  }
274
298
 
275
- /** One virtual column of `tables/cytables.xml`. */
299
+ /**
300
+ * One virtual column of `tables/cytables.xml`.
301
+ * @category Plugin helpers
302
+ */
276
303
  export interface VirtualColumn {
277
304
  /** The column name in the target table. */
278
305
  readonly name: string;
@@ -325,6 +352,14 @@ export async function virtualColumnsOf(
325
352
  continue;
326
353
  }
327
354
  const targetKey = target.columns.findIndex((c) => c.name === virtual.targetJoinKey);
355
+ if (targetKey < 0) {
356
+ report.error(
357
+ "parse-error",
358
+ CYS_ISSUE.TABLE,
359
+ `${target.entry}: the virtual column "${virtual.name}" joins on the column "${virtual.targetJoinKey}", which the table does not have; the column is not read`,
360
+ );
361
+ continue;
362
+ }
328
363
  const values = new Map<string, string>();
329
364
  for (const [key, cells] of target.rows) {
330
365
  const join = targetKey <= 0 ? key : cells[targetKey];
@@ -388,6 +423,9 @@ async function resolve(
388
423
  // re-key the chained values (by the chained source's join key) to this source's join key
389
424
  const values = new Map<string, string>();
390
425
  const chainedJoin = source.columns.findIndex((c) => c.name === chained.targetJoinKey);
426
+ if (chainedJoin < 0) {
427
+ return `reads the virtual column "${chained.name}", which joins on the column "${chained.targetJoinKey}" its table does not have`;
428
+ }
391
429
  for (const [key, cells] of source.rows) {
392
430
  const lookup = chainedJoin <= 0 ? key : cells[chainedJoin];
393
431
  const value = lookup === undefined ? undefined : inner.values.get(lookup);