@graphty/graph-io 0.3.25 → 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,5 +1,5 @@
1
1
  /**
2
- * Option normalisation for importers and exporters (design sections 8.4 and 8.5): every common
2
+ * Option normalization for importers and exporters (design sections 8.4 and 8.5): every common
3
3
  * option resolved to its documented default, enum values checked (E_UNSUPPORTED, the core's
4
4
  * convention for an option outside its set), and the per-format defaults (`ids`, `defaultDirected`,
5
5
  * `weightFrom`, `addMissingNodes`) supplied by the importer that calls resolveImportOptions().
@@ -16,9 +16,13 @@ import {
16
16
  SINK_OPTION_CODE,
17
17
  } from "./codes.js";
18
18
  import { canonicalEncoding } from "./input.js";
19
+ import { plural } from "./plural.js";
19
20
  import { type ImportReportBuilder } from "./report.js";
20
21
 
21
- /** The defaults an importer supplies for the options whose default is per format (design section 8.4). */
22
+ /**
23
+ * The defaults an importer supplies for the options whose default is per format.
24
+ * @category Plugin helpers
25
+ */
22
26
  export interface ImportFormatDefaults {
23
27
  /** "canonical" for text-cell formats, "keep" for JSON. */
24
28
  readonly ids: IdCoercion;
@@ -31,9 +35,9 @@ export interface ImportFormatDefaults {
31
35
  }
32
36
 
33
37
  /**
34
- * CommonImportOptions with every field present (design section 8.4 defaults applied).
35
- * Consumed by the per-format importers and exporters under src/formats.
38
+ * CommonImportOptions with every field present.
36
39
  * @public
40
+ * @category Plugin helpers
37
41
  */
38
42
  export interface ResolvedImportOptions {
39
43
  /** The id coercion rule. */
@@ -70,7 +74,10 @@ export interface ResolvedImportOptions {
70
74
  readonly encoding: string | null;
71
75
  }
72
76
 
73
- /** CommonExportOptions with every field present (design section 8.5 defaults applied). */
77
+ /**
78
+ * CommonExportOptions with every field present.
79
+ * @category Plugin helpers
80
+ */
74
81
  export interface ResolvedExportOptions {
75
82
  /** "error" never renames a node; "mangle" rewrites and keeps the original. */
76
83
  readonly sanitizeIds: "error" | "mangle";
@@ -89,7 +96,10 @@ const LONG_MODES: ReadonlySet<string> = new Set(["f64", "string"]);
89
96
  const HYPEREDGE_POLICIES: ReadonlySet<string> = new Set(["error", "skip", "star", "clique"]);
90
97
  const SANITIZE_MODES: ReadonlySet<string> = new Set(["error", "mangle"]);
91
98
 
92
- /** The default error limit of design section 8.4. */
99
+ /**
100
+ * The default error limit: errors tolerated before an import aborts.
101
+ * @category Reports and errors
102
+ */
93
103
  export const DEFAULT_ERROR_LIMIT = 100;
94
104
 
95
105
  export { SINK_OPTION_CODE };
@@ -98,17 +108,18 @@ export { SINK_OPTION_CODE };
98
108
  const SINK_OPTION_NAMES = ["addMissingNodes", "duplicateEdges", "selfLoops", "weightDtype"] as const;
99
109
 
100
110
  /**
101
- * Report every builder-policy option the caller explicitly requested that the sink does not use
102
- * (design section 8.4 precedence), one `W_SINK_OPTION` warning per option with the option name as
111
+ * Report every builder-policy option the caller explicitly requested that the sink does not use,
112
+ * one `W_SINK_OPTION` warning per option with the option name as
103
113
  * the element. Options left undefined are never reported: they are defaults, not requests. On the
104
114
  * registry's builder, which is seeded from the same options, nothing is ever reported.
105
115
  * @param sink - the sink the importer pushes into
106
116
  * @param options - the caller's raw options, possibly undefined
107
117
  * @param report - the report to record into
108
118
  * @param enforcesMissingNodes - true when the importer applies `addMissingNodes: false` itself (it
109
- * refuses unknown endpoints before the sink sees them), so that request is honoured on any sink and
119
+ * refuses unknown endpoints before the sink sees them), so that request is honored on any sink and
110
120
  * only `addMissingNodes: true` against a refusing sink is reported
111
121
  * @returns the number of warnings recorded
122
+ * @category Writing a format
112
123
  */
113
124
  export function reportSinkOptions(
114
125
  sink: GraphSink,
@@ -156,15 +167,28 @@ const IGNORABLE_OPTION_NAMES = [
156
167
  "hyperedges",
157
168
  ] as const;
158
169
 
170
+ /** The defaults that are the same in every format (the others, such as `defaultDirected`, differ by format). */
171
+ const FIXED_DEFAULTS: Readonly<Partial<Record<(typeof IGNORABLE_OPTION_NAMES)[number], unknown>>> = {
172
+ nodeIdFrom: "id",
173
+ duplicateEdges: "keep",
174
+ selfLoops: "keep",
175
+ onMixedDirection: "expand",
176
+ weightDtype: "f64",
177
+ long: "f64",
178
+ restoreMangledIds: true,
179
+ hyperedges: "skip",
180
+ };
181
+
159
182
  /**
160
183
  * Report every common option the caller set to a non-default value that the format has no use
161
- * for (design section 8.4: "the importer reports every option it could not honour"): one
184
+ * for: one
162
185
  * `W_OPTION_IGNORED` warning (category `unsupported`) per option, the option name as the element.
163
186
  * The builder-policy options are reportSinkOptions()'s and are skipped here.
164
187
  * @param options - the caller's raw options, possibly undefined
165
188
  * @param report - the report to record into
166
189
  * @param used - the common option names the importer reads
167
190
  * @returns the number of warnings recorded
191
+ * @category Writing a format
168
192
  */
169
193
  export function reportUnusedOptions(
170
194
  options: CommonImportOptions | undefined,
@@ -180,7 +204,8 @@ export function reportUnusedOptions(
180
204
  continue;
181
205
  }
182
206
  const value: unknown = options[name];
183
- if (value === undefined) {
207
+ if (value === undefined || value === FIXED_DEFAULTS[name]) {
208
+ // an option spelled out at its default changes nothing, whether or not the format reads it
184
209
  continue;
185
210
  }
186
211
  report.warning(
@@ -194,6 +219,29 @@ export function reportUnusedOptions(
194
219
  return recorded;
195
220
  }
196
221
 
222
+ /**
223
+ * Whether the caller chose a graph with `graphIndex` or `graphName`. An importer warns
224
+ * W_MULTIPLE_GRAPHS about the graphs it skipped only when it read the first by default.
225
+ * @param options - the caller's graphIndex / graphName
226
+ * @returns true when either option is set
227
+ * @category Writing a format
228
+ */
229
+ export function graphChosen(options: GraphChoiceOptions | undefined): boolean {
230
+ return options?.graphIndex !== undefined || options?.graphName !== undefined;
231
+ }
232
+
233
+ /**
234
+ * The graphs of an input as an E_GRAPH_NOT_FOUND message lists them: their indexes and names, so the
235
+ * caller can choose without a second call.
236
+ * @param names - each graph's name, null for an unnamed graph
237
+ * @returns the text to append, starting with "; "
238
+ */
239
+ function graphNamesText(names: readonly (string | null)[]): string {
240
+ const shown = names.slice(0, 10).map((n, i) => `${i} ${n === null ? "(unnamed)" : JSON.stringify(n)}`);
241
+ const more = names.length > shown.length ? `, and ${names.length - shown.length} more` : "";
242
+ return `; the file holds ${shown.join(", ")}${more}`;
243
+ }
244
+
197
245
  /**
198
246
  * The graph an importer reads from an input that holds several: the one `graphIndex` or
199
247
  * `graphName` names, else the first. A choice that names no graph is E_GRAPH_NOT_FOUND, a name two
@@ -203,6 +251,7 @@ export function reportUnusedOptions(
203
251
  * @param options - the caller's graphIndex / graphName
204
252
  * @param report - the report a failure is recorded in
205
253
  * @returns the index of the graph to read; E_UNSUPPORTED for an option of the wrong type, or both
254
+ * @category Writing a format
206
255
  */
207
256
  export function chooseGraph(
208
257
  names: readonly (string | null)[],
@@ -250,7 +299,7 @@ export function chooseGraph(
250
299
  if (matches.length === 0) {
251
300
  return report.fail(
252
301
  GRAPH_NOT_FOUND_CODE,
253
- `graphName ${JSON.stringify(graphName)} names none of the ${names.length} graph(s)`,
302
+ `graphName ${JSON.stringify(graphName)} names none of the ${names.length} graph${plural(names.length)}${graphNamesText(names)}`,
254
303
  { element: graphName },
255
304
  { names: [...names] },
256
305
  );
@@ -259,17 +308,21 @@ export function chooseGraph(
259
308
  }
260
309
  const index = graphIndex ?? 0;
261
310
  if (index >= names.length) {
262
- return report.fail(GRAPH_NOT_FOUND_CODE, `graphIndex ${index} is beyond the ${names.length} graph(s)`);
311
+ return report.fail(
312
+ GRAPH_NOT_FOUND_CODE,
313
+ `graphIndex ${index} is beyond the ${names.length} graph${plural(names.length)}${graphNamesText(names)}`,
314
+ );
263
315
  }
264
316
  return index;
265
317
  }
266
318
 
267
319
  /**
268
- * Apply the design section 8.4 defaults to an importer's common options and check every enum
320
+ * Apply the documented defaults to an importer's common options and check every enum
269
321
  * value. Format-specific options in the same object are ignored here.
270
322
  * @param options - the caller's options, possibly undefined
271
323
  * @param defaults - the importer's per-format defaults
272
324
  * @returns the resolved options; E_UNSUPPORTED for a value outside its set
325
+ * @category Writing a format
273
326
  */
274
327
  export function resolveImportOptions(
275
328
  options: CommonImportOptions | undefined,
@@ -297,9 +350,10 @@ export function resolveImportOptions(
297
350
  }
298
351
 
299
352
  /**
300
- * Apply the design section 8.5 defaults to an exporter's common options and check the enum values.
353
+ * Apply the documented defaults to an exporter's common options and check the enum values.
301
354
  * @param options - the caller's options, possibly undefined
302
355
  * @returns the resolved options; E_UNSUPPORTED for a value outside its set
356
+ * @category Writing a format
303
357
  */
304
358
  export function resolveExportOptions(options: CommonExportOptions | undefined): ResolvedExportOptions {
305
359
  const o: CommonExportOptions = options ?? {};
@@ -450,10 +504,51 @@ function encodingOption(value: unknown): string | null {
450
504
  return canonical;
451
505
  }
452
506
 
507
+ /**
508
+ * The options to pass to another importer that you hand text you already decoded with readText():
509
+ * the caller's options without `encoding` and `onProgress`, which that text no longer needs. Without
510
+ * this, the other importer would warn that `encoding` has no effect on text, and report progress a
511
+ * second time.
512
+ * @example
513
+ * ```ts
514
+ * const text = await readText(input, report, opts);
515
+ * report.include(await csvImporter.import(text, sink, forDecodedText(options)));
516
+ * ```
517
+ * @param options - the caller's import options
518
+ * @returns a copy without `encoding` and `onProgress`
519
+ * @category Writing a format
520
+ */
521
+ export function forDecodedText<O extends CommonImportOptions>(options: O | undefined): O {
522
+ return { ...options, encoding: undefined, onProgress: undefined } as O;
523
+ }
524
+
525
+ /**
526
+ * The dialect names of the built-in formats with a `dialect` save option. One options object shared between formats
527
+ * can hold one format's dialect, and the other formats ignore it, as they ignore any option they do not have.
528
+ */
529
+ export const FORMAT_DIALECTS: Readonly<Record<string, readonly string[]>> = Object.freeze({
530
+ csv: Object.freeze(["gephi", "generic"]),
531
+ json: Object.freeze(["node-link", "d3", "jgf", "cytoscape", "graphology", "vis", "obographs"]),
532
+ });
533
+
534
+ /**
535
+ * Whether a `dialect` value names another format's dialect, which this format ignores rather than refuses.
536
+ * @param format - this format
537
+ * @param value - the caller's `dialect` option
538
+ * @returns true for another built-in format's dialect name
539
+ */
540
+ export function otherFormatDialect(format: string, value: unknown): boolean {
541
+ return (
542
+ typeof value === "string" &&
543
+ Object.entries(FORMAT_DIALECTS).some(([f, names]) => f !== format && names.includes(value))
544
+ );
545
+ }
546
+
453
547
  /**
454
548
  * A short description of an option value for an error message.
455
549
  * @param value - the value
456
550
  * @returns the JSON text of a primitive, or the type name otherwise
551
+ * @category Plugin helpers
457
552
  */
458
553
  export function describe(value: unknown): string {
459
554
  switch (typeof value) {
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Count agreement for messages, so a report says "1 node is" and "3 nodes are", never "1 node(s) are".
3
+ */
4
+
5
+ /**
6
+ * The plural ending of a regular noun after a count.
7
+ * @param n - the count
8
+ * @returns "" for 1, "s" otherwise
9
+ */
10
+ export function plural(n: number): string {
11
+ return n === 1 ? "" : "s";
12
+ }
13
+
14
+ /**
15
+ * The form of a verb that agrees with a count.
16
+ * @param n - the count
17
+ * @param one - the form for 1 ("is", "was", "holds")
18
+ * @param many - the form for any other count ("are", "were", "hold")
19
+ * @returns `one` or `many`
20
+ */
21
+ export function agree(n: number, one: string, many: string): string {
22
+ return n === 1 ? one : many;
23
+ }
24
+
25
+ /**
26
+ * A count of nodes and edges, leaving out a zero: "2 nodes and 1 edge", "1 edge".
27
+ * @param nodes - the node count
28
+ * @param edges - the edge count
29
+ * @returns the text
30
+ */
31
+ export function elementCount(nodes: number, edges: number): string {
32
+ const parts = [];
33
+ if (nodes > 0 || edges === 0) {
34
+ parts.push(`${nodes} node${plural(nodes)}`);
35
+ }
36
+ if (edges > 0) {
37
+ parts.push(`${edges} edge${plural(edges)}`);
38
+ }
39
+ return parts.join(" and ");
40
+ }
41
+
42
+ /**
43
+ * A word with its indefinite article, chosen by its first letter: "an integer", "a double".
44
+ * @param word - the word
45
+ * @returns "a word" or "an word"
46
+ */
47
+ export function withArticle(word: string): string {
48
+ return `${/^[aeiou]/i.test(word) ? "an" : "a"} ${word}`;
49
+ }
@@ -13,11 +13,20 @@
13
13
  import { GraphFormatError, type GraphFormatErrorCode } from "@graphty/graph-format";
14
14
 
15
15
  import { ImportError, type ImportIssue, type ImportReport, type IssueCategory, type LossNote } from "../types.js";
16
+ import { ISSUES_SUPPRESSED_CODE } from "./codes.js";
17
+ import { agree, plural } from "./plural.js";
18
+
19
+ /**
20
+ * The most warnings of one code a report keeps; later ones are counted in one W_ISSUES_SUPPRESSED
21
+ * warning, so a per-row warning on a large file cannot grow the report without bound.
22
+ * @category Issue and loss codes
23
+ */
24
+ export const MAX_WARNINGS_PER_CODE = 1000;
16
25
 
17
26
  /**
18
27
  * Where an issue was found: the 1-based line and the element (id or attribute name) when known.
19
- * Consumed by the per-format importers and exporters under src/formats.
20
28
  * @public
29
+ * @category Writing a format
21
30
  */
22
31
  export interface IssueLocation {
23
32
  /** The 1-based source line, when known. */
@@ -28,8 +37,8 @@ export interface IssueLocation {
28
37
 
29
38
  /**
30
39
  * The mutable element counters of a report in progress; importers increment them directly in hot loops.
31
- * Consumed by the per-format importers and exporters under src/formats.
32
40
  * @public
41
+ * @category Plugin helpers
33
42
  */
34
43
  export interface MutableCounts {
35
44
  /** Nodes pushed. */
@@ -40,7 +49,7 @@ export interface MutableCounts {
40
49
  skippedNodes: number;
41
50
  /** Edges skipped after an error. */
42
51
  skippedEdges: number;
43
- /** Source edges expanded into two logical edges (design section 3.6). */
52
+ /** Source edges expanded into two logical edges. */
44
53
  expandedMixed: number;
45
54
  }
46
55
 
@@ -60,18 +69,30 @@ const CATEGORY_BY_CODE: Readonly<Partial<Record<GraphFormatErrorCode, IssueCateg
60
69
  };
61
70
 
62
71
  /**
63
- * The code a report used to give a thrown value that was not a GraphFormatError. Since audit round
64
- * 1 such a value (a TypeError, a RangeError: a bug in an importer or a sink, never a defect of the
65
- * input) propagates out of import() untouched, so no importer records this code any more; the
66
- * constant stays for consumers that switch on the codes of earlier reports.
72
+ * No longer recorded; kept so code that switches on older reports still compiles.
73
+ * @category Issue and loss codes
67
74
  */
68
75
  export const PARSE_ERROR_CODE = "E_PARSE";
69
76
 
77
+ /**
78
+ * An issue message as the ImportError shows it: prefixed with its line when the issue has one and the
79
+ * message does not already name it.
80
+ * @param message - the issue message
81
+ * @param where - the issue location
82
+ * @returns the message for the error
83
+ */
84
+ function withLine(message: string, where: IssueLocation | undefined): string {
85
+ const line = where?.line;
86
+ return line === undefined || line === null || message.includes(`line ${line}`)
87
+ ? message
88
+ : `line ${line}: ${message}`;
89
+ }
90
+
70
91
  /**
71
92
  * Accumulates an ImportReport while an importer runs. Errors count toward the error limit; the
72
93
  * error that takes the count beyond the limit is still recorded, `truncated` is set, and an
73
- * ImportError carrying the report so far is thrown (design section 8.4: "beyond it the importer
74
- * aborts with E_IMPORT"). Warnings never abort.
94
+ * ImportError carrying the report so far is thrown. Warnings never abort.
95
+ * @category Writing a format
75
96
  */
76
97
  export class ImportReportBuilder {
77
98
  /** The importer's format name. */
@@ -89,6 +110,9 @@ export class ImportReportBuilder {
89
110
 
90
111
  private readonly onceCodes = new Set<string>();
91
112
 
113
+ /** Warnings recorded per code, kept or not. */
114
+ private readonly warningsByCode = new Map<string, number>();
115
+
92
116
  private errors = 0;
93
117
 
94
118
  private warnings = 0;
@@ -163,7 +187,7 @@ export class ImportReportBuilder {
163
187
  this.errors++;
164
188
  if (this.errors > this.errorLimit) {
165
189
  this.truncatedFlag = true;
166
- throw this.abort(`error limit of ${this.errorLimit} exceeded: ${message}`, {
190
+ throw this.abort(`error limit of ${this.errorLimit} exceeded: ${withLine(message, where)}`, {
167
191
  code,
168
192
  limit: this.errorLimit,
169
193
  });
@@ -172,7 +196,9 @@ export class ImportReportBuilder {
172
196
  }
173
197
 
174
198
  /**
175
- * Record a warning; warnings never count toward the limit.
199
+ * Record a warning; warnings never count toward the limit. Beyond MAX_WARNINGS_PER_CODE
200
+ * warnings of one code the warning is counted, not kept: finish() adds one W_ISSUES_SUPPRESSED
201
+ * warning per such code with the number dropped.
176
202
  * @param category - the issue category
177
203
  * @param code - a stable code such as "W_WIDENED"
178
204
  * @param message - a plain-ASCII message
@@ -181,8 +207,12 @@ export class ImportReportBuilder {
181
207
  */
182
208
  warning(category: IssueCategory, code: string, message: string, where?: IssueLocation): ImportIssue {
183
209
  const issue = makeIssue(category, "warning", code, message, where);
184
- this.issueList.push(issue);
185
- this.warnings++;
210
+ const seen = (this.warningsByCode.get(code) ?? 0) + 1;
211
+ this.warningsByCode.set(code, seen);
212
+ if (seen <= MAX_WARNINGS_PER_CODE) {
213
+ this.issueList.push(issue);
214
+ this.warnings++;
215
+ }
186
216
  return issue;
187
217
  }
188
218
 
@@ -226,7 +256,7 @@ export class ImportReportBuilder {
226
256
  }
227
257
 
228
258
  /**
229
- * The per-element catch of design section 8.6: record a thrown GraphFormatError as an error
259
+ * The per-element catch: record a thrown GraphFormatError as an error
230
260
  * issue with its code and the category the code implies. Anything else is re-thrown unchanged:
231
261
  * an ImportError (the import already aborted), an abort reason, and any other thrown value (a
232
262
  * TypeError or RangeError is a programming error in the importer or the sink, never a defect of
@@ -238,11 +268,38 @@ export class ImportReportBuilder {
238
268
  recordError(err: unknown, where?: IssueLocation): ImportIssue {
239
269
  if (err instanceof GraphFormatError && !(err instanceof ImportError)) {
240
270
  const category = CATEGORY_BY_CODE[err.code] ?? "validation-error";
271
+ if (err.code === "E_TOO_LARGE") {
272
+ // the sink is full: every later element would fail the same way, so the import stops
273
+ return this.failWith(category, err.code, err.message, where);
274
+ }
241
275
  return this.error(category, err.code, err.message, where);
242
276
  }
243
277
  throw err;
244
278
  }
245
279
 
280
+ /**
281
+ * A builder that starts from everything this one recorded so far: issues, counts, loss notes,
282
+ * the warnOnce keys, the error and warning counts and the truncation flag. For an importer that
283
+ * reads its input once and emits several graphs, each with its own report.
284
+ * @returns the copy; later records to either builder do not reach the other
285
+ */
286
+ fork(): ImportReportBuilder {
287
+ const copy = new ImportReportBuilder(this.format, this.errorLimit);
288
+ Object.assign(copy.counts, this.counts);
289
+ copy.issueList.push(...this.issueList);
290
+ copy.lossList.push(...this.lossList);
291
+ for (const key of this.onceCodes) {
292
+ copy.onceCodes.add(key);
293
+ }
294
+ for (const [code, count] of this.warningsByCode) {
295
+ copy.warningsByCode.set(code, count);
296
+ }
297
+ copy.errors = this.errors;
298
+ copy.warnings = this.warnings;
299
+ copy.truncatedFlag = this.truncatedFlag;
300
+ return copy;
301
+ }
302
+
246
303
  /**
247
304
  * Build the ImportError that aborts the import, carrying the report so far. The caller throws
248
305
  * it; this method only constructs it so it can be used in expression position.
@@ -263,13 +320,65 @@ export class ImportReportBuilder {
263
320
  * @param details - optional machine-readable context for the ImportError
264
321
  */
265
322
  fail(code: string, message: string, where?: IssueLocation, details?: Readonly<Record<string, unknown>>): never {
266
- const issue = makeIssue("parse-error", "error", code, message, where);
267
- this.issueList.push(issue);
323
+ this.failWith("parse-error", code, message, where, details);
324
+ }
325
+
326
+ /**
327
+ * Record a fatal error of any category and abort, as fail() does for a parse error: a size
328
+ * limit (E_TOO_LARGE, category "unsupported") stops an import without being a defect of the
329
+ * syntax. A fatal error is not the error limit: `truncated` stays as it was.
330
+ * @param category - the issue category
331
+ * @param code - a stable code
332
+ * @param message - a plain-ASCII message
333
+ * @param where - the line and element, when known
334
+ * @param details - optional machine-readable context for the ImportError
335
+ */
336
+ failWith(
337
+ category: IssueCategory,
338
+ code: string,
339
+ message: string,
340
+ where?: IssueLocation,
341
+ details?: Readonly<Record<string, unknown>>,
342
+ ): never {
343
+ this.issueList.push(makeIssue(category, "error", code, message, where));
268
344
  this.errors++;
269
- if (this.errors > this.errorLimit) {
270
- this.truncatedFlag = true;
345
+ throw this.abort(withLine(message, where), { code, ...details });
346
+ }
347
+
348
+ /**
349
+ * Add a finished report to this one: its issues after the ones recorded so far, its counts, its
350
+ * loss notes and its truncated flag. Use it when an importer hands part of the work to another
351
+ * importer (for example, a wrapper around the CSV importer) and returns one report for both. The issues
352
+ * keep their codes; errors added this way do not count toward this report's error limit, since
353
+ * the other importer applied its own.
354
+ * @param report - the report the other importer returned
355
+ * @returns this builder
356
+ * @example
357
+ * ```ts
358
+ * const report = new ImportReportBuilder("netscope", opts.errorLimit);
359
+ * const text = await readText(input, report, opts);
360
+ * report.include(await csvImporter.import(text, sink, options));
361
+ * return report.finish();
362
+ * ```
363
+ */
364
+ include(report: ImportReport): this {
365
+ for (const issue of report.issues) {
366
+ this.issueList.push(issue);
367
+ if (issue.severity === "error") {
368
+ this.errors++;
369
+ } else {
370
+ this.warnings++;
371
+ }
271
372
  }
272
- throw this.abort(message, { code, ...details });
373
+ const { counts } = report;
374
+ this.counts.nodes += counts.nodes;
375
+ this.counts.edges += counts.edges;
376
+ this.counts.skippedNodes += counts.skippedNodes;
377
+ this.counts.skippedEdges += counts.skippedEdges;
378
+ this.counts.expandedMixed += counts.expandedMixed;
379
+ this.lossList.push(...report.lossy);
380
+ this.truncatedFlag ||= report.truncated;
381
+ return this;
273
382
  }
274
383
 
275
384
  /**
@@ -279,12 +388,27 @@ export class ImportReportBuilder {
279
388
  */
280
389
  finish(): ImportReport {
281
390
  const { nodes, edges, skippedNodes, skippedEdges, expandedMixed } = this.counts;
391
+ const suppressed: ImportIssue[] = [];
392
+ for (const [code, seen] of this.warningsByCode) {
393
+ if (seen > MAX_WARNINGS_PER_CODE) {
394
+ const more = seen - MAX_WARNINGS_PER_CODE;
395
+ suppressed.push(
396
+ makeIssue(
397
+ "unsupported",
398
+ "warning",
399
+ ISSUES_SUPPRESSED_CODE,
400
+ `${more} more ${code} warning${plural(more)} ${agree(more, "was", "were")} not kept (the report keeps the first ${MAX_WARNINGS_PER_CODE})`,
401
+ { element: code },
402
+ ),
403
+ );
404
+ }
405
+ }
282
406
  return Object.freeze({
283
407
  format: this.format,
284
408
  counts: Object.freeze({ nodes, edges, skippedNodes, skippedEdges, expandedMixed }),
285
- issues: Object.freeze([...this.issueList]),
409
+ issues: Object.freeze([...this.issueList, ...suppressed]),
286
410
  errorCount: this.errors,
287
- warningCount: this.warnings,
411
+ warningCount: this.warnings + suppressed.length,
288
412
  truncated: this.truncatedFlag,
289
413
  lossy: Object.freeze([...this.lossList]),
290
414
  durationMs: now() - this.startedAt,
@@ -319,19 +443,38 @@ function makeIssue(
319
443
  }
320
444
 
321
445
  /**
322
- * Whether a thrown value is an abort reason (the DOMException or Error named "AbortError" that
323
- * AbortSignal.reason holds), which an importer must let through untouched.
446
+ * Whether a thrown value means the load was cancelled rather than failed: the DOMException or Error
447
+ * named "AbortError" that an aborted signal throws, or the "TimeoutError" of AbortSignal.timeout().
448
+ * Use it in a `catch` block to say nothing to the user when they cancelled. A custom reason passed
449
+ * to `abort(reason)` is not recognized: compare it with `signal.reason`. A format plugin uses it to
450
+ * let a cancellation through untouched.
324
451
  * @param err - the thrown value
325
- * @returns true for an AbortError
452
+ * @returns true for an AbortError or a TimeoutError
453
+ * @example
454
+ * ```ts
455
+ * try {
456
+ * await loadFromUrl(url, { signal });
457
+ * } catch (err) {
458
+ * if (!isAbortError(err)) {
459
+ * showError(err);
460
+ * }
461
+ * }
462
+ * ```
463
+ * @category Reports and errors
326
464
  */
327
465
  export function isAbortError(err: unknown): boolean {
328
- return typeof err === "object" && err !== null && (err as { name?: unknown }).name === "AbortError";
466
+ if (typeof err !== "object" || err === null) {
467
+ return false;
468
+ }
469
+ const { name } = err as { name?: unknown };
470
+ return name === "AbortError" || name === "TimeoutError";
329
471
  }
330
472
 
331
473
  /**
332
474
  * The message of a thrown value: an Error's message, a string as is, anything else described by type.
333
475
  * @param err - the thrown value
334
476
  * @returns a plain message
477
+ * @category Plugin helpers
335
478
  */
336
479
  export function messageOf(err: unknown): string {
337
480
  if (err instanceof Error) {