@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
@@ -36,15 +36,15 @@ import { type ImportReportBuilder } from "./report.js";
36
36
 
37
37
  /**
38
38
  * The direction of one source edge.
39
- * Consumed by the per-format importers and exporters under src/formats.
40
39
  * @public
40
+ * @category Plugin helpers
41
41
  */
42
42
  export type EdgeKind = "directed" | "undirected" | "mutual";
43
43
 
44
44
  /**
45
45
  * Where an edge or header was read, for issues.
46
- * Consumed by the per-format importers and exporters under src/formats.
47
46
  * @public
47
+ * @category Plugin helpers
48
48
  */
49
49
  export interface EdgeLocation {
50
50
  /** The 1-based line, when known. */
@@ -53,13 +53,24 @@ export interface EdgeLocation {
53
53
  readonly element?: string | null | undefined;
54
54
  }
55
55
 
56
- /** The name of the bool edge column marking source-directed edges (design section 3.6). */
56
+ /**
57
+ * The name of the bool edge column that, in a graph with both directed and undirected edges, says
58
+ * which edges were directed in the file (true) and which were undirected (false).
59
+ * @category Plugin helpers
60
+ */
57
61
  export const DIRECTED_COLUMN = "graphty.directed";
58
62
 
59
- /** The name of the u32 edge column pairing the halves of an expanded edge (design section 3.6). */
63
+ /**
64
+ * The name of the edge column that links the two edges an undirected edge is stored as, in a graph
65
+ * with both directed and undirected edges: each holds the index of the other.
66
+ * @category Plugin helpers
67
+ */
60
68
  export const PAIR_COLUMN = "graphty.pair";
61
69
 
62
- /** The name of the bool edge column marking GEXF mutual edges (design section 3.6). */
70
+ /**
71
+ * The name of the bool edge column that marks a GEXF `mutual` edge.
72
+ * @category Plugin helpers
73
+ */
63
74
  export const MUTUAL_COLUMN = "graphty.mutual";
64
75
 
65
76
  export { DIRECTION_FORCED_CODE, DIRECTION_REFUSED_CODE, MIXED_DIRECTION_CODE };
@@ -69,8 +80,11 @@ const PAIR_DECL: ColumnDecl = { name: PAIR_COLUMN, dtype: "u32", role: "pair", r
69
80
  const MUTUAL_DECL: ColumnDecl = { name: MUTUAL_COLUMN, dtype: "bool", role: "mutual" };
70
81
 
71
82
  /**
72
- * Pushes edges into a sink while resolving direction per design section 8.4. One instance per
73
- * import call; `setHeader()` before the first `addEdge()`.
83
+ * Adds edges to the sink and handles files whose edges have different directions, the way
84
+ * `onMixedDirection` asks. Make one per import call, call `setHeader()` once with the direction the
85
+ * file declares, then `addEdge()` for each edge. In a directed graph an undirected edge is stored as
86
+ * two edges, one each way, linked so an exporter writes them back as one.
87
+ * @category Writing a format
74
88
  */
75
89
  export class DirectionResolver {
76
90
  private readonly sink: GraphSink;
@@ -118,20 +132,19 @@ export class DirectionResolver {
118
132
  }
119
133
 
120
134
  /**
121
- * Whether the reserved direction columns exist (the sink holds expanded edges).
122
- * @returns true once graphty.pair was declared or adopted
135
+ * Whether the graph holds undirected edges stored as two edges.
136
+ * @returns true once the first such edge was added
123
137
  */
124
138
  get expanded(): boolean {
125
139
  return this.pairHandle !== INVALID_INDEX;
126
140
  }
127
141
 
128
142
  /**
129
- * Rule 1 of design section 8.4: set the sink's direction from the file's header (or the
130
- * `defaultDirected` option for a file that declares none) before the first edge. Under the
131
- * "directed" / "undirected" policies the policy's direction is used instead and the difference
132
- * is reported. A refusal (E_DIRECTED: locked, or a non-empty directed sink for an undirected
133
- * header) is recorded as a coercion issue and the sink's direction stands; a non-empty unlocked
134
- * undirected sink with a directed header is expanded in place.
143
+ * Set the graph's direction before the first edge: the direction the file declares, or the
144
+ * `defaultDirected` option for a file that declares none. Under `onMixedDirection` "directed" or
145
+ * "undirected" that direction is used instead, with a warning when it differs. When the sink
146
+ * cannot change direction (a caller's builder that already holds edges or was locked), the
147
+ * sink's direction stands and a warning is recorded.
135
148
  * @param headerDirected - the direction the file declares (or the default)
136
149
  * @param where - the line of the header, when known
137
150
  */
@@ -141,11 +154,13 @@ export class DirectionResolver {
141
154
  if (this.policy === "directed" || this.policy === "undirected") {
142
155
  wanted = this.policy === "directed";
143
156
  if (wanted !== headerDirected) {
144
- this.report.warning(
157
+ // once: this says it for every edge, so no edge repeats it
158
+ this.report.warnOnce(
145
159
  "coercion",
146
160
  DIRECTION_FORCED_CODE,
147
161
  `the file declares ${direction(headerDirected)} edges; read as ${direction(wanted)} per onMixedDirection`,
148
162
  { line: where?.line ?? null },
163
+ `${DIRECTION_FORCED_CODE}:${direction(headerDirected)}`,
149
164
  );
150
165
  }
151
166
  }
@@ -188,24 +203,27 @@ export class DirectionResolver {
188
203
  }
189
204
 
190
205
  /**
191
- * The mirror half of the edge most recently pushed by addEdge(), when it was expanded into a
192
- * pair; INVALID_INDEX otherwise. An importer that learns an edge's weight after pushing it
193
- * (a GEXF attvalue) sets it on both halves.
194
- * @returns the mirror's logical index, or INVALID_INDEX
206
+ * The second edge of the edge the last addEdge() call added, when that edge was stored as two;
207
+ * otherwise INVALID_INDEX (4294967295). An edge attribute or weight you set after addEdge()
208
+ * belongs on both: set it on the index addEdge() returned and, when this is not INVALID_INDEX,
209
+ * on this index too.
210
+ * @returns the second edge's index, or INVALID_INDEX
195
211
  */
196
212
  get lastMirror(): number {
197
213
  return this.mirrorOfLast;
198
214
  }
199
215
 
200
216
  /**
201
- * Rule 2 of design section 8.4: push one source edge. An edge whose direction equals the
202
- * sink's is one addEdge; one that differs is expanded, forced or refused per the policy.
217
+ * Add one edge. An edge with the graph's direction is added as it is; one with the other
218
+ * direction is stored as two edges, given the graph's direction, or refused, as
219
+ * `onMixedDirection` says. When it is stored as two, the return value is the first and
220
+ * `lastMirror` the second.
203
221
  * @param source - the source id
204
222
  * @param target - the target id
205
223
  * @param kind - the edge's direction in the file
206
224
  * @param weight - the weight, or undefined when the file gives none
207
225
  * @param where - the line and element, for issues
208
- * @returns the logical index of the (primary) edge
226
+ * @returns the index of the edge added (the first one, when it was stored as two)
209
227
  */
210
228
  addEdge(source: NodeId, target: NodeId, kind: EdgeKind, weight?: number, where?: EdgeLocation): number {
211
229
  if (!this.headerSet) {
@@ -234,6 +252,7 @@ export class DirectionResolver {
234
252
  DIRECTION_FORCED_CODE,
235
253
  `${kind} edges read as ${direction(sink.directed)} per onMixedDirection`,
236
254
  where,
255
+ `${DIRECTION_FORCED_CODE}:${kind}`,
237
256
  );
238
257
  const e = sink.addEdge(source, target, weight);
239
258
  this.track(e);
@@ -263,7 +282,8 @@ export class DirectionResolver {
263
282
  }
264
283
 
265
284
  /**
266
- * How many edges were pushed with a direction other than their own under the forcing policies.
285
+ * How many edges were given a direction other than their own, under `onMixedDirection`
286
+ * "directed" or "undirected".
267
287
  * @returns the count
268
288
  */
269
289
  get forced(): number {
@@ -407,61 +427,68 @@ function direction(directed: boolean): string {
407
427
  // ============================================================ the exporter side
408
428
 
409
429
  /**
410
- * The expanded-pair view of a snapshot's logical edges for exporters (design sections 3.6 and
411
- * 8.5): which edges are the mirror half of an expanded pair (and are folded back into their
412
- * primary), which were undirected in the source, and which carry the GEXF mutual mark. One
413
- * implementation for every exporter; the only per-format choice is whether a mutual pair folds
414
- * back into one edge (`foldMutual`, for formats with a mutual or undirected slot) or is written as
415
- * two directed edges (the default).
416
- * Consumed by the per-format exporters under src/formats.
430
+ * What an exporter needs to know about edge direction, from `pairFolding(snapshot)`. In a graph
431
+ * with both directed and undirected edges, each undirected edge is stored as two edges, one each
432
+ * way. `folded(e)` tells you which of the two to skip, so the edge is written once, and
433
+ * `sourceDirected(e)` whether an edge was directed. A GEXF `mutual` edge is also stored as two
434
+ * edges; it is written as two directed edges unless you pass `foldMutual: true`.
417
435
  * @public
436
+ * @category Plugin helpers
418
437
  */
419
438
  export interface PairFolding {
420
- /** Whether the snapshot carries expanded pairs at all (the pair role column exists). */
439
+ /** Whether the graph holds any edge stored as two edges. When false, every method answers as for a plain edge. */
421
440
  readonly expanded: boolean;
422
- /** The number of mutual primaries (edges with the mutual mark whose mirror exists). */
441
+ /** How many GEXF mutual edges the graph holds, each counted once. */
423
442
  readonly mutualCount: number;
424
443
  /**
425
- * Whether an edge is the mirror half of a pair the exporter folds (its primary is written).
426
- * @param e - the logical edge index
444
+ * Whether to skip an edge: true for the second of the two edges an undirected edge (or, with
445
+ * `foldMutual`, a mutual edge) is stored as. Write the first and skip this one.
446
+ * @param e - the edge index
427
447
  * @returns true when the edge must be skipped
428
448
  */
429
449
  folded(e: number): boolean;
430
450
  /**
431
- * The other half of an expanded pair.
432
- * @param e - the logical edge index
433
- * @returns the mate's index, or INVALID_INDEX when the edge is not paired
451
+ * The other of the two edges an undirected or mutual edge is stored as.
452
+ * @param e - the edge index
453
+ * @returns the other edge's index, or INVALID_INDEX (4294967295) for an edge stored once
434
454
  */
435
455
  mateOf(e: number): number;
436
456
  /**
437
- * Whether an edge was directed in the source (true for every edge of a snapshot without the
438
- * directed role column, and for an undirected snapshot's edges as far as the column says).
439
- * @param e - the logical edge index
440
- * @returns the source direction
457
+ * Whether an edge was directed in the file it was read from: false for an undirected edge of a
458
+ * graph with both kinds. It is true for every edge of a graph without mixed direction, an
459
+ * undirected graph included, so the direction to write for edge `e` is
460
+ * `snapshot.directed && sourceDirected(e)`.
461
+ * @param e - the edge index
462
+ * @returns whether the edge is directed
441
463
  */
442
464
  sourceDirected(e: number): boolean;
443
465
  /**
444
- * Whether an edge is a mutual primary or mirror (the GEXF `mutual` type).
445
- * @param e - the logical edge index
466
+ * Whether an edge is either of the two edges a GEXF `mutual` edge is stored as.
467
+ * @param e - the edge index
446
468
  * @returns true for a mutual edge
447
469
  */
448
470
  isMutual(e: number): boolean;
449
471
  }
450
472
 
451
- /** The per-format choice of pairFolding(). */
473
+ /**
474
+ * The per-format choice of pairFolding().
475
+ * @category Plugin helpers
476
+ */
452
477
  export interface PairFoldingOptions {
453
478
  /**
454
- * Fold a mutual pair back into its primary (a format with a mutual or undirected slot);
455
- * false (the default) writes both halves as directed edges, and the caller reports the mark.
479
+ * Write a GEXF mutual edge once, for a format that can say an edge goes both ways. When false
480
+ * (the default), `folded()` keeps both of its edges, so it is written as two directed edges.
456
481
  */
457
482
  readonly foldMutual?: boolean | undefined;
458
483
  }
459
484
 
460
485
  /**
461
- * Build the pair-folding view of a snapshot (one pass over the role columns).
462
- * @param snapshot - the snapshot
463
- * @param options - the per-format choice
464
- * @returns the view
486
+ * Read how a snapshot stores edge direction, for an exporter: which edges to skip so each
487
+ * undirected edge is written once, and which edges were directed.
488
+ * @param snapshot - the graph to write
489
+ * @param options - whether a GEXF mutual edge is written once
490
+ * @returns the answers, per edge
491
+ * @category Writing a format
465
492
  */
466
493
  export function pairFolding(snapshot: GraphSnapshot, options: PairFoldingOptions = {}): PairFolding {
467
494
  const foldMutual = options.foldMutual ?? false;
@@ -29,6 +29,7 @@ const XML_REPLACEMENTS: Readonly<Record<string, string>> = {
29
29
  * surrogate) has no XML spelling at all and is E_COLUMN_TYPE; the exporters' check() counts them.
30
30
  * @param text - the text
31
31
  * @returns the escaped text
32
+ * @category Plugin helpers
32
33
  */
33
34
  export function escapeXmlText(text: string): string {
34
35
  if (hasIllegalXmlChar(text)) {
@@ -39,9 +40,10 @@ export function escapeXmlText(text: string): string {
39
40
 
40
41
  /**
41
42
  * Escape text for a double-quoted XML attribute value: `&`, `<`, `>`, `"` and the whitespace
42
- * characters attribute normalisation would fold; a character XML 1.0 forbids is E_COLUMN_TYPE.
43
+ * characters attribute normalization would fold; a character XML 1.0 forbids is E_COLUMN_TYPE.
43
44
  * @param text - the text
44
45
  * @returns the escaped text
46
+ * @category Plugin helpers
45
47
  */
46
48
  export function escapeXmlAttribute(text: string): string {
47
49
  if (hasIllegalXmlChar(text)) {
@@ -71,6 +73,7 @@ const GML_SPECIAL = /["&]|[^ -~]/gu;
71
73
  * A lone surrogate cannot be written and is E_COLUMN_TYPE.
72
74
  * @param text - the text
73
75
  * @returns the quoted GML string
76
+ * @category Plugin helpers
74
77
  */
75
78
  export function quoteGmlString(text: string): string {
76
79
  const escaped = text.replace(GML_SPECIAL, (c) => {
@@ -116,18 +119,23 @@ const GML_NAMED: ReadonlyMap<string, string> = (() => {
116
119
  /**
117
120
  * Decode the character entities of a GML string body (the inverse of quoteGmlString on the text
118
121
  * between the quotes): numeric references, the XML entities and the ISO-8859-1 HTML entities. An
119
- * unknown named entity is left as written and handed to `onUnknown`.
122
+ * unknown named entity, or a numeric reference beyond U+10FFFF, is left as written and handed to
123
+ * `onUnknown`.
120
124
  * @param body - the text between the quotes
121
- * @param onUnknown - called with each unknown named entity (`&name;`), when given
125
+ * @param onUnknown - called with each entity left as written (`&name;`, `&#99999999;`), when given
122
126
  * @returns the decoded text
127
+ * @category Plugin helpers
123
128
  */
124
129
  export function decodeGmlString(body: string, onUnknown?: (entity: string) => void): string {
125
130
  return body.replace(GML_ENTITY, (whole, entity: string) => {
126
- if (entity.startsWith("#x")) {
127
- return String.fromCodePoint(Number.parseInt(entity.slice(2), 16));
128
- }
129
131
  if (entity.startsWith("#")) {
130
- return String.fromCodePoint(Number.parseInt(entity.slice(1), 10));
132
+ const code = entity.startsWith("#x") ? Number.parseInt(entity.slice(2), 16) : Number(entity.slice(1));
133
+ if (code <= 0x10ffff) {
134
+ return String.fromCodePoint(code);
135
+ }
136
+ // beyond Unicode: no character to decode to, kept as written like an unknown name
137
+ onUnknown?.(whole);
138
+ return whole;
131
139
  }
132
140
  const known = GML_NAMED.get(entity);
133
141
  if (known === undefined) {
@@ -146,6 +154,7 @@ const DOT_KEYWORDS: ReadonlySet<string> = new Set(["node", "edge", "graph", "dig
146
154
  * a digit, or a numeral, and not a keyword (case-insensitive).
147
155
  * @param text - the text
148
156
  * @returns true when the text can be written bare
157
+ * @category Plugin helpers
149
158
  */
150
159
  export function isBareDotId(text: string): boolean {
151
160
  if (DOT_KEYWORDS.has(text.toLowerCase())) {
@@ -184,6 +193,7 @@ function isDotIdentifier(text: string): boolean {
184
193
  * the closing quote. Every other text is writable; quoteDotId() writes it.
185
194
  * @param text - the id, name or value text
186
195
  * @returns true when quoteDotId(text) reads back as `text`
196
+ * @category Plugin helpers
187
197
  */
188
198
  export function isWritableDotText(text: string): boolean {
189
199
  return !text.endsWith("\\") && !text.includes('\\"') && !/\\[\r\n]/.test(text);
@@ -196,6 +206,7 @@ export function isWritableDotText(text: string): boolean {
196
206
  * backslash has no DOT spelling (isWritableDotText); the caller refuses it before writing.
197
207
  * @param text - the id or label text
198
208
  * @returns the DOT ID
209
+ * @category Plugin helpers
199
210
  */
200
211
  export function quoteDotId(text: string): string {
201
212
  if (isBareDotId(text)) {
@@ -205,29 +216,31 @@ export function quoteDotId(text: string): string {
205
216
  }
206
217
 
207
218
  /**
208
- * Write a set CSV cell per RFC 4180: quoted with `"` doubled when the text contains the
209
- * delimiter, a quote, a CR or LF, or leading / trailing whitespace; bare otherwise. The empty
210
- * string is written as the quoted empty cell `""`, so the importers can tell a set empty string
211
- * (and an empty-string node id, legal under design section 4.1) from an unset cell, which every
212
- * exporter writes as nothing between the delimiters.
219
+ * Write a set CSV cell per RFC 4180: quoted, with the quote character doubled, when the text
220
+ * contains the delimiter, the quote character, a CR or LF, or leading / trailing whitespace; bare
221
+ * otherwise. The empty string is written as an empty quoted cell (`""`), so the importers can tell a
222
+ * set empty string (and an empty-string node id) from an unset cell, which every exporter writes as
223
+ * nothing between the delimiters.
213
224
  * @param text - the cell text of a set cell
214
225
  * @param delimiter - the field delimiter (default ",")
226
+ * @param quote - the quote character (default `"`)
215
227
  * @returns the cell as written
228
+ * @category Plugin helpers
216
229
  */
217
- export function quoteCsvCell(text: string, delimiter = ","): string {
230
+ export function quoteCsvCell(text: string, delimiter = ",", quote = '"'): string {
218
231
  if (text.length === 0) {
219
- return '""';
232
+ return quote + quote;
220
233
  }
221
234
  if (
222
235
  !text.includes(delimiter) &&
223
- !text.includes('"') &&
236
+ !text.includes(quote) &&
224
237
  !text.includes("\n") &&
225
238
  !text.includes("\r") &&
226
239
  text === text.trim()
227
240
  ) {
228
241
  return text;
229
242
  }
230
- return `"${text.replace(/"/g, '""')}"`;
243
+ return `${quote}${text.split(quote).join(quote + quote)}${quote}`;
231
244
  }
232
245
 
233
246
  /**
@@ -235,6 +248,7 @@ export function quoteCsvCell(text: string, delimiter = ","): string {
235
248
  * labels, so a text containing a double quote, a CR or an LF cannot be written.
236
249
  * @param text - the label text
237
250
  * @returns true when quotePajekLabel() can write it
251
+ * @category Plugin helpers
238
252
  */
239
253
  export function isPajekLabel(text: string): boolean {
240
254
  return !text.includes('"') && !text.includes("\n") && !text.includes("\r");
@@ -247,6 +261,7 @@ export function isPajekLabel(text: string): boolean {
247
261
  * the exporter's check() counts those.
248
262
  * @param text - the label text
249
263
  * @returns the label as written
264
+ * @category Plugin helpers
250
265
  */
251
266
  export function quotePajekLabel(text: string): string {
252
267
  if (!isPajekLabel(text)) {
@@ -255,7 +270,8 @@ export function quotePajekLabel(text: string): string {
255
270
  value: text,
256
271
  });
257
272
  }
258
- if (text.length > 0 && !/[\s"]/.test(text) && !text.startsWith("[")) {
273
+ // a bare `%` token starts a comment for the importer, so such a text is quoted too
274
+ if (text.length > 0 && !/[\s"]/.test(text) && !text.startsWith("[") && !text.startsWith("%")) {
259
275
  return text;
260
276
  }
261
277
  return `"${text}"`;