@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
@@ -27,7 +27,7 @@
27
27
  * as the DOT grammar says).
28
28
  *
29
29
  * The whole text is read first (design section 8.4 allows it for DOT). A grammar violation is
30
- * fatal, as it is for Graphviz itself: the import aborts with ImportError (code E_DOT_SYNTAX)
30
+ * fatal, as it is for Graphviz itself: the import aborts with ImportError (issue code E_SYNTAX)
31
31
  * carrying the partial report. Errors the sink raises for one element are recorded and the element
32
32
  * is skipped (section 8.6).
33
33
  */
@@ -42,36 +42,53 @@ import {
42
42
  } from "@graphty/graph-format";
43
43
 
44
44
  import { declareResolved } from "../../common/attributes.js";
45
+ import { importChosenGraph } from "../../common/choose.js";
45
46
  import {
47
+ AMBIGUOUS_GRAPH_NAME_CODE,
46
48
  COLUMN_RENAMED_CODE,
47
49
  DIRECTION_FORCED_CODE,
48
50
  DIRECTION_REFUSED_CODE,
51
+ DUPLICATE_ATTRIBUTE_CODE,
52
+ ELEMENT_ISSUE,
49
53
  EMPTY_INPUT_CODE,
54
+ ENCODING_CONFLICT_CODE,
50
55
  ENCODING_FALLBACK_CODE,
56
+ GRAPH_NOT_FOUND_CODE,
51
57
  ID_MERGED_CODE,
58
+ INPUT_ISSUE,
52
59
  INVALID_ENCODING_CODE,
53
60
  INVALID_UTF8_CODE,
54
61
  MIXED_DIRECTION_CODE,
55
62
  MULTIPLE_GRAPHS_CODE,
56
63
  OPTION_IGNORED_CODE,
64
+ PRECISION_CODE,
57
65
  ROLE_TAKEN_CODE,
58
66
  SINK_OPTION_CODE,
59
67
  SYNTAX_CODE,
60
68
  UNKNOWN_ENCODING_CODE,
61
69
  } from "../../common/codes.js";
62
70
  import { DirectionResolver, type EdgeKind } from "../../common/direction.js";
71
+ import { survivesF32 } from "../../common/format.js";
63
72
  import { IdCoercer } from "../../common/ids.js";
64
- import { readText, throwIfAborted } from "../../common/input.js";
73
+ import { canonicalEncoding, readText, throwIfAborted } from "../../common/input.js";
65
74
  import {
75
+ graphChosen,
66
76
  reportSinkOptions,
67
77
  reportUnusedOptions,
68
78
  type ResolvedImportOptions,
69
79
  resolveImportOptions,
70
80
  } from "../../common/options.js";
81
+ import { plural } from "../../common/plural.js";
71
82
  import { ImportReportBuilder } from "../../common/report.js";
72
83
  import { inferTextDtype, parseTextCell, TextCellWriter, WIDENING_UNSUPPORTED_CODE } from "../../common/text.js";
73
84
  import { parseWeightText } from "../../common/weights.js";
74
- import { type CommonImportOptions, type GraphImporter, type ImportInput, type ImportReport } from "../../types.js";
85
+ import {
86
+ type CommonImportOptions,
87
+ type GraphChoiceOptions,
88
+ type GraphImporter,
89
+ type ImportInput,
90
+ type ImportReport,
91
+ } from "../../types.js";
75
92
  import {
76
93
  CLUSTER_COLUMN,
77
94
  DOT_FORMAT,
@@ -86,46 +103,70 @@ import {
86
103
  } from "./names.js";
87
104
  import { DotSyntaxError, type DotToken, DotTokenizer } from "./tokenizer.js";
88
105
 
89
- /** The DOT importer's format-specific options. */
90
- export interface DotImportOptions {
106
+ /**
107
+ * The DOT importer's format-specific options.
108
+ * @category Built-in formats
109
+ */
110
+ export interface DotImportOptions extends GraphChoiceOptions, CommonImportOptions {
91
111
  /**
92
112
  * What an edge operator that contradicts the graph keyword means (`--` in a digraph, `->` in a
93
- * graph; a syntax error for Graphviz): "operator" (default) reads the edge with the operator's
94
- * direction and resolves it per onMixedDirection, with a warning; "header" reads it with the
95
- * graph's direction, with a warning; "error" aborts the import as Graphviz does.
113
+ * graph; Graphviz refuses such a file): "operator" reads the edge with the operator's
114
+ * direction, so the graph has both directions and `onMixedDirection` decides, with a warning;
115
+ * "header" reads it with the graph's direction, with a warning; "error" stops the import with an
116
+ * ImportError whose `issue.code` is E_SYNTAX, as Graphviz does.
117
+ * @defaultValue "operator"
96
118
  */
97
119
  mismatchedEdgeOperator?: "operator" | "header" | "error" | undefined;
98
120
  /**
99
- * Map a node's `pos` to a `pos` column with the position role and a trailing `!` to `pin`
100
- * (default true); false keeps `pos` as the text the file wrote, like any other attribute.
121
+ * Read a node's `pos` attribute as its position (a trailing `!` becomes a `pin` attribute);
122
+ * false keeps `pos` as the text the file wrote, like any other attribute.
123
+ * @defaultValue true
101
124
  */
102
125
  positions?: boolean | undefined;
103
126
  }
104
127
 
105
128
  /**
106
- * The issue codes the DOT importer records (design section 8.6), by name: the codes shared with
107
- * the other importers (src/common/codes.ts) and the DOT-specific ones. A key is the code without
129
+ * The issue codes the DOT importer records, by name: the codes shared with
130
+ * the other importers and the DOT-specific ones. A key is the code without
108
131
  * its severity and format prefixes.
132
+ * @category Built-in formats
109
133
  */
110
134
  export const DOT_ISSUE = Object.freeze({
111
- /** A grammar violation; fatal. */
135
+ ...INPUT_ISSUE,
136
+ ...ELEMENT_ISSUE,
137
+ /** The text breaks DOT's syntax; the message says where. The import stops. */
112
138
  SYNTAX: SYNTAX_CODE,
113
- /** The input holds no graph at all (empty or only comments); fatal. */
139
+ /** The input holds no graph: it is empty or only comments. The import stops. */
114
140
  EMPTY_INPUT: EMPTY_INPUT_CODE,
115
- /** The input holds invalid UTF-8 (fatal). */
141
+ /** The input is not valid UTF-8. The import stops. */
116
142
  INVALID_UTF8: INVALID_UTF8_CODE,
117
- /** Invalid bytes in the encoding a BOM, a declaration or the encoding option chose (fatal). */
143
+ /**
144
+ * Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
145
+ * `encoding` option). The import stops.
146
+ */
118
147
  INVALID_ENCODING: INVALID_ENCODING_CODE,
119
148
  /** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
120
149
  ENCODING_FALLBACK: ENCODING_FALLBACK_CODE,
121
150
  /** A declared encoding the platform cannot decode was ignored. */
122
151
  UNKNOWN_ENCODING: UNKNOWN_ENCODING_CODE,
123
- /** Subgraphs or braces nested deeper than the parser's limit; fatal. */
152
+ /** A declared encoding the byte order mark contradicts (the mark wins). */
153
+ ENCODING_CONFLICT: ENCODING_CONFLICT_CODE,
154
+ /** Subgraphs or braces are nested deeper than graph-io reads. The import stops. */
124
155
  NESTING: "E_DOT_NESTING",
125
- /** An edge operator contradicting the graph keyword (warning under "operator" / "header"). */
156
+ /**
157
+ * An edge operator contradicting the graph keyword, read under mismatchedEdgeOperator "operator" or "header".
158
+ * Under "error" the import stops with E_SYNTAX instead.
159
+ */
126
160
  EDGE_OPERATOR: "W_DOT_EDGE_OPERATOR",
127
- /** A second graph in the same input; only the first is read. */
161
+ /**
162
+ * The file holds several graphs and only the first was read. It is not added when `graphIndex` or `graphName` chose the graph.
163
+ * `importAllGraphs()` reads every one.
164
+ */
128
165
  MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
166
+ /** `graphIndex` or `graphName` names no graph of the file; the message lists the graphs it holds. The import stops. */
167
+ GRAPH_NOT_FOUND: GRAPH_NOT_FOUND_CODE,
168
+ /** `graphName` matches more than one graph; pass `graphIndex`. The import stops. */
169
+ AMBIGUOUS_GRAPH_NAME: AMBIGUOUS_GRAPH_NAME_CODE,
129
170
  /** A badly delimited numeral (`1e3`) split into two tokens, as Graphviz does with a warning. */
130
171
  NUMERAL_AMBIGUITY: "W_DOT_NUMERAL_AMBIGUITY",
131
172
  /** Attributes of a subgraph that is not a cluster (rank=same and the like) cannot be represented. */
@@ -136,29 +177,59 @@ export const DOT_ISSUE = Object.freeze({
136
177
  CLUSTER_NODE_MERGED: "W_DOT_CLUSTER_NODE_MERGED",
137
178
  /** A node mentioned in two unrelated clusters keeps the first. */
138
179
  CLUSTER_CONFLICT: "W_DOT_CLUSTER_CONFLICT",
139
- /** A node `pos` that is not a point; the value was dropped. */
180
+ /** A node's `pos` is not a point, or is too large for a 32-bit float position; the value was dropped. */
140
181
  BAD_POS: "W_DOT_BAD_POS",
182
+ /** Node `pos` values mix two and three coordinates; the position column records the first's. */
183
+ POS_DIMS: "W_DOT_POS_DIMS",
184
+ /** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
185
+ PRECISION: PRECISION_CODE,
186
+ /** The same attribute twice in one statement's attribute lists; the last value stands, as in Graphviz. */
187
+ DUPLICATE_ATTRIBUTE: DUPLICATE_ATTRIBUTE_CODE,
188
+ /** The second part of a port (`a:p:zz`) is not a compass point; kept as written, as Graphviz warns. */
189
+ COMPASS_POINT: "W_DOT_COMPASS_POINT",
190
+ /** A `charset` attribute beyond the head the decoder reads it from; the input was decoded without it. */
191
+ LATE_CHARSET: "W_DOT_LATE_CHARSET",
192
+
141
193
  /** A parallel edge merged into an earlier one under `strict`. */
142
194
  STRICT_MERGED: "W_DOT_STRICT_MERGED",
143
195
  /** An edge merged into an earlier one with the same endpoints and `key`. */
144
196
  KEY_MERGED: "W_DOT_KEY_MERGED",
145
- /** A role (label, id, position, ...) was already taken in the caller's sink; the column was declared without it. */
197
+ /**
198
+ * You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
199
+ * a plain attribute.
200
+ */
146
201
  ROLE_TAKEN: ROLE_TAKEN_CODE,
147
- /** A column of another shape exists in the caller's sink under a name the importer declares; renamed `<name>#<id>`. */
202
+ /**
203
+ * An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example
204
+ * two attributes declared with the same name.
205
+ */
148
206
  COLUMN_RENAMED: COLUMN_RENAMED_CODE,
149
- /** A common option the format has no use for was given a non-default value. */
207
+ /** You set an option this format does not use; it had no effect. The message names the option. */
150
208
  OPTION_IGNORED: OPTION_IGNORED_CODE,
151
- /** Two distinct id texts merged under ids: "number". */
209
+ /** Two different id texts became the same number because `ids` is "number", so their nodes were merged. */
152
210
  ID_MERGED: ID_MERGED_CODE,
153
- /** A builder-policy option the sink does not honour. */
211
+ /**
212
+ * You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
213
+ * `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
214
+ */
154
215
  SINK_OPTION: SINK_OPTION_CODE,
155
- /** The sink refused the file's direction. */
216
+ /**
217
+ * You read into a graph builder whose direction is already set, or which already holds edges, so the file is read
218
+ * with the builder's direction instead of its own.
219
+ */
156
220
  DIRECTION_REFUSED: DIRECTION_REFUSED_CODE,
157
- /** Edges forced to the policy's direction. */
221
+ /** Edges of the other direction were read with the direction `onMixedDirection` chose. */
158
222
  DIRECTION_FORCED: DIRECTION_FORCED_CODE,
159
- /** A mixed file under onMixedDirection "error" (fatal). */
223
+ /**
224
+ * The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
225
+ * format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
226
+ * it anyway.
227
+ */
160
228
  MIXED_DIRECTION: MIXED_DIRECTION_CODE,
161
- /** A text column the sink could not widen to the dtype its cells imply. */
229
+ /**
230
+ * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of
231
+ * its first values.
232
+ */
162
233
  WIDENING_UNSUPPORTED: WIDENING_UNSUPPORTED_CODE,
163
234
  });
164
235
 
@@ -192,8 +263,17 @@ const MAX_ANCESTOR_WALK = 4096;
192
263
  */
193
264
  const DOT_HEADER = /^\s*(strict\s+)?(di)?graph(?=[\s{"/]|$)(?!\s*\[)/i;
194
265
  const TRUE_TEXTS: ReadonlySet<string> = new Set(["true", "yes", "1"]);
195
- const POINT_TEXT =
196
- /^\s*([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)\s*,\s*([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)(?:\s*,\s*([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?))?\s*(!?)\s*$/;
266
+ const COMPASS_POINTS: ReadonlySet<string> = new Set(["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "_"]);
267
+ /**
268
+ * A DOT number: digits with an optional fraction, or a bare fraction (`.5`), then an exponent.
269
+ * Written so each digit has exactly one way to match; `[0-9]*\.?[0-9]+` took quadratic time on a
270
+ * long run of digits.
271
+ */
272
+ const POINT_NUMBER = String.raw`[-+]?(?:\d+(?:\.\d+)?|\.\d+)(?:[eE][-+]?\d+)?`;
273
+ /** A point "x,y[,z][!]". The `!` and its trailing space are one optional group, so spaces cannot split two ways. */
274
+ const POINT_TEXT = new RegExp(
275
+ String.raw`^\s*(${POINT_NUMBER})\s*,\s*(${POINT_NUMBER})(?:\s*,\s*(${POINT_NUMBER}))?\s*(?:(!)\s*)?$`,
276
+ );
197
277
 
198
278
  /** An attribute as written: name, value text and the line of the assignment. */
199
279
  interface DotAttribute {
@@ -239,10 +319,12 @@ interface Scope {
239
319
  }
240
320
 
241
321
  /**
242
- * The importer plugin for DOT / Graphviz text (design section 12.4).
322
+ * The importer plugin for DOT / Graphviz text.
323
+ * @category Built-in formats
243
324
  */
244
325
  export const dotImporter: GraphImporter<DotImportOptions> = Object.freeze({
245
326
  format: DOT_FORMAT,
327
+ options: Object.freeze(["mismatchedEdgeOperator", "positions"]),
246
328
  extensions: EXTENSIONS,
247
329
  mimeTypes: MIME_TYPES,
248
330
 
@@ -273,6 +355,10 @@ export const dotImporter: GraphImporter<DotImportOptions> = Object.freeze({
273
355
  sink: GraphSink,
274
356
  options?: DotImportOptions & CommonImportOptions,
275
357
  ): Promise<ImportReport> {
358
+ if (graphChosen(options)) {
359
+ // the choice is honored here too, not only by the registry
360
+ return importChosenGraph(dotImporter, input, sink, options);
361
+ }
276
362
  const resolved = resolveImportOptions(options, {
277
363
  ids: "canonical",
278
364
  defaultDirected: true,
@@ -282,21 +368,25 @@ export const dotImporter: GraphImporter<DotImportOptions> = Object.freeze({
282
368
  const report = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
283
369
  reportUnusedOptions(options, report, USED_OPTIONS);
284
370
  reportSinkOptions(sink, options, report);
285
- const text = await readText(input, report, { ...resolved, declaredEncoding: dotCharset });
371
+ const head: { charset?: string | null } = {};
372
+ const text = await readText(input, report, {
373
+ ...resolved,
374
+ declaredEncoding: (h) => (head.charset = dotCharset(h)),
375
+ declarationBytes: CHARSET_HEAD_BYTES,
376
+ });
286
377
  const reports = { current: report };
287
378
  const lexer = dotLexer(text, reports);
288
379
  const first = guard(report, () => lexer.next());
289
- const trailing = parseGraph(
290
- new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false),
291
- report,
292
- first,
293
- );
380
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
381
+ parser.headCharset = head.charset;
382
+ const trailing = parseGraph(parser, report, first);
294
383
  if (trailing.kind !== "eof") {
384
+ // anything after the graph must be graphs too: Graphviz refuses the file otherwise
295
385
  const skipped = guard(report, () => countGraphs(lexer, trailing));
296
386
  report.warning(
297
387
  "unsupported",
298
388
  MULTIPLE_GRAPHS_CODE,
299
- `the input holds ${skipped} more graph(s) after the first; import() reads the first, importAll() reads every one`,
389
+ `the input holds ${skipped} more graph${plural(skipped)} after the first; the first is read (graphIndex or graphName chooses another; importAllGraphs() reads every one)`,
300
390
  { line: trailing.line },
301
391
  );
302
392
  }
@@ -325,7 +415,12 @@ export const dotImporter: GraphImporter<DotImportOptions> = Object.freeze({
325
415
  const mismatch = mismatchOption(options?.mismatchedEdgeOperator);
326
416
  const first = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
327
417
  reportUnusedOptions(options, first, USED_OPTIONS);
328
- const text = await readText(input, first, { ...resolved, declaredEncoding: dotCharset });
418
+ const head: { charset?: string | null } = {};
419
+ const text = await readText(input, first, {
420
+ ...resolved,
421
+ declaredEncoding: (h) => (head.charset = dotCharset(h)),
422
+ declarationBytes: CHARSET_HEAD_BYTES,
423
+ });
329
424
  const reports = { current: first };
330
425
  const lexer = dotLexer(text, reports);
331
426
  const done: ImportReport[] = [];
@@ -335,11 +430,9 @@ export const dotImporter: GraphImporter<DotImportOptions> = Object.freeze({
335
430
  reports.current = report;
336
431
  const sink = sinkFor(done.length);
337
432
  reportSinkOptions(sink, options, report);
338
- token = parseGraph(
339
- new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false),
340
- report,
341
- token,
342
- );
433
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
434
+ parser.headCharset = head.charset;
435
+ token = parseGraph(parser, report, token);
343
436
  throwIfAborted(resolved.signal);
344
437
  done.push(report.finish());
345
438
  } while (token.kind !== "eof");
@@ -408,6 +501,9 @@ function countGraphs(lexer: DotTokenizer, first: DotToken): number {
408
501
  if (isKeyword(token, "strict")) {
409
502
  token = lexer.next();
410
503
  }
504
+ if (isPunct(token, "}")) {
505
+ throw new DotSyntaxError('unexpected "}" after the end of the graph: no "{" is open', token.line);
506
+ }
411
507
  if (!isKeyword(token, "graph") && !isKeyword(token, "digraph")) {
412
508
  throw new DotSyntaxError(`expected "graph" or "digraph", found ${describeToken(token)}`, token.line);
413
509
  }
@@ -435,19 +531,47 @@ function countGraphs(lexer: DotTokenizer, first: DotToken): number {
435
531
  return count;
436
532
  }
437
533
 
438
- /** A `charset` attribute assignment (Graphviz's declaration of the input encoding). */
439
- const DOT_CHARSET = /\bcharset\s*=\s*"?([A-Za-z][A-Za-z0-9._-]*)/i;
534
+ /** How many leading bytes the `charset` search sees: a license comment may come before the graph. */
535
+ const CHARSET_HEAD_BYTES = 64 * 1024;
440
536
 
441
537
  /**
442
538
  * The encoding a DOT file declares with the graph attribute `charset` (Graphviz reads UTF-8,
443
539
  * Latin1 and Big-5), for the shared byte decoder; Graphviz's spellings `latin-1` and `big-5` are
444
- * mapped to the WHATWG labels.
540
+ * mapped to the WHATWG labels. Only a graph-level assignment counts (`charset=...` as a statement
541
+ * or inside `graph [...]`), never one in a comment, a quoted value or a node / edge attribute list.
445
542
  * @param head - the start of the file, decoded as windows-1252
446
543
  * @returns the declared label, or null
447
544
  */
448
545
  function dotCharset(head: string): string | null {
449
- const match = DOT_CHARSET.exec(head);
450
- return match === null ? null : match[1].replace(/^(latin|big)-/i, "$1");
546
+ const lexer = new DotTokenizer(head);
547
+ // the attribute list an open `[` belongs to: the graph's (`graph [`) or a node's / an edge's
548
+ let list: "graph" | "other" | null = null;
549
+ let previous: DotToken | null = null;
550
+ try {
551
+ let token = lexer.next();
552
+ while (token.kind !== "eof") {
553
+ if (isPunct(token, "[")) {
554
+ list = previous !== null && isKeyword(previous, "graph") ? "graph" : "other";
555
+ } else if (isPunct(token, "]")) {
556
+ list = null;
557
+ } else if (list !== "other" && isKeyword(token, "charset")) {
558
+ const equals = lexer.next();
559
+ const value = isPunct(equals, "=") ? lexer.next() : equals;
560
+ if (value !== equals && value.kind === "id") {
561
+ return value.text.replace(/^(latin|big)-/i, "$1");
562
+ }
563
+ token = value;
564
+ }
565
+ previous = token;
566
+ token = lexer.next();
567
+ }
568
+ } catch (err) {
569
+ // the head ends inside a comment or a string: nothing further is seen
570
+ if (!(err instanceof DotSyntaxError)) {
571
+ throw err;
572
+ }
573
+ }
574
+ return null;
451
575
  }
452
576
 
453
577
  /**
@@ -612,6 +736,16 @@ class DotParser {
612
736
  /** The current subgraph nesting depth. */
613
737
  private depth = 0;
614
738
 
739
+ /** The coordinate count of the first `pos`, or 0 before one. */
740
+ private posDims = 0;
741
+
742
+ /**
743
+ * What the decoder's look at the head found for `charset`: a label, null for none, undefined
744
+ * when it never looked (text input, a BOM, the encoding option). A `charset` assignment read
745
+ * when the head had none came too late to decode by.
746
+ */
747
+ headCharset: string | null | undefined = undefined;
748
+
615
749
  /** The inferred attribute columns by name, per domain (the 5.1 text grammar per column). */
616
750
  private readonly nodeWriters = new Map<string, TextCellWriter>();
617
751
 
@@ -833,7 +967,16 @@ class DotParser {
833
967
  let { text } = this.identifier();
834
968
  if (isPunct(lexer.peek(), ":")) {
835
969
  lexer.next();
836
- text += `:${this.identifier().text}`;
970
+ const compass = this.identifier();
971
+ text += `:${compass.text}`;
972
+ if (!COMPASS_POINTS.has(compass.text)) {
973
+ this.report.warning(
974
+ "validation-error",
975
+ DOT_ISSUE.COMPASS_POINT,
976
+ `port ${JSON.stringify(text)}: ${JSON.stringify(compass.text)} is not a compass point (n, ne, e, se, s, sw, w, nw, c, _); the port is kept as written`,
977
+ { line: compass.line, element: text },
978
+ );
979
+ }
837
980
  }
838
981
  return text;
839
982
  }
@@ -1082,6 +1225,7 @@ class DotParser {
1082
1225
  private attributeList(): DotAttribute[] {
1083
1226
  const { lexer } = this;
1084
1227
  const out: DotAttribute[] = [];
1228
+ const names = new Set<string>();
1085
1229
  while (isPunct(lexer.peek(), "[")) {
1086
1230
  lexer.next();
1087
1231
  for (;;) {
@@ -1103,6 +1247,15 @@ class DotParser {
1103
1247
  );
1104
1248
  }
1105
1249
  const value = this.identifier();
1250
+ if (names.has(name.text)) {
1251
+ this.report.warning(
1252
+ "merged",
1253
+ DOT_ISSUE.DUPLICATE_ATTRIBUTE,
1254
+ `attribute ${JSON.stringify(name.text)} is set twice in one statement; the last value ${JSON.stringify(value.text)} stands`,
1255
+ { line: name.line, element: name.text },
1256
+ );
1257
+ }
1258
+ names.add(name.text);
1106
1259
  out.push({ name: name.text, value: value.text, line: name.line });
1107
1260
  }
1108
1261
  }
@@ -1205,7 +1358,7 @@ class DotParser {
1205
1358
  this.report.warnOnce(
1206
1359
  "coercion",
1207
1360
  DOT_ISSUE.EDGE_OPERATOR,
1208
- `${message}; read with the operator's direction and resolved per onMixedDirection`,
1361
+ `${message}; read with the operator's direction, and onMixedDirection decides how the mixed graph is stored`,
1209
1362
  { line: op.line },
1210
1363
  );
1211
1364
  return operatorDirected ? "directed" : "undirected";
@@ -1308,7 +1461,7 @@ class DotParser {
1308
1461
  const weightText = weightFrom === null ? undefined : effective.get(weightFrom);
1309
1462
  if (weightText !== undefined) {
1310
1463
  try {
1311
- weight = parseWeightText(weightText);
1464
+ weight = parseWeightText(weightText, this.report);
1312
1465
  } catch (err) {
1313
1466
  this.report.recordError(err, where);
1314
1467
  this.report.counts.skippedEdges++;
@@ -1470,6 +1623,17 @@ class DotParser {
1470
1623
  * @param attribute - the attribute
1471
1624
  */
1472
1625
  private setGraphAttribute(attribute: DotAttribute): void {
1626
+ if (attribute.name.toLowerCase() === "charset" && this.headCharset === null) {
1627
+ const canonical = canonicalEncoding(attribute.value);
1628
+ if (canonical !== "utf-8") {
1629
+ this.report.warning(
1630
+ "unsupported",
1631
+ DOT_ISSUE.LATE_CHARSET,
1632
+ `charset ${JSON.stringify(attribute.value)} is declared beyond the first 1024 bytes, after the input was decoded without it; pass the encoding option to decode it as declared`,
1633
+ { line: attribute.line, element: attribute.name },
1634
+ );
1635
+ }
1636
+ }
1473
1637
  try {
1474
1638
  if (attribute.name === LABEL_ATTRIBUTE) {
1475
1639
  this.sink.setGraphValue(attribute.name, attribute.value, { dtype: "string", origin: DOT_ORIGIN });
@@ -1507,7 +1671,37 @@ class DotParser {
1507
1671
  const y = Number(match[2]);
1508
1672
  const z = match[3] === undefined ? 0 : Number(match[3]);
1509
1673
  const dims = match[3] === undefined ? 2 : 3;
1510
- this.sink.setNodeValue(this.positionColumn(dims), index, [x, y, z]);
1674
+ const point = [x, y, z];
1675
+ if (point.some((v) => !Number.isFinite(Math.fround(v)))) {
1676
+ // the position column is f32: a half-infinite point would be a half-valid position
1677
+ this.report.warning(
1678
+ "validation-error",
1679
+ DOT_ISSUE.BAD_POS,
1680
+ `pos ${JSON.stringify(text)} is beyond the f32 range of the position column; dropped`,
1681
+ { line, element },
1682
+ );
1683
+ return;
1684
+ }
1685
+ if (!point.every(survivesF32)) {
1686
+ this.report.warnOnce(
1687
+ "precision",
1688
+ DOT_ISSUE.PRECISION,
1689
+ `pos ${JSON.stringify(text)} has a coordinate the f32 position column rounds (warned once; positions=false keeps pos as written)`,
1690
+ { line, element },
1691
+ `${DOT_ISSUE.PRECISION}:pos`,
1692
+ );
1693
+ }
1694
+ if (this.posDims === 0) {
1695
+ this.posDims = dims;
1696
+ } else if (dims !== this.posDims) {
1697
+ this.report.warnOnce(
1698
+ "validation-error",
1699
+ DOT_ISSUE.POS_DIMS,
1700
+ `pos values mix ${this.posDims} and ${dims} coordinates; the position column records sourceDims ${this.posDims}`,
1701
+ { line, element },
1702
+ );
1703
+ }
1704
+ this.sink.setNodeValue(this.positionColumn(dims), index, point);
1511
1705
  if (match[4] === "!") {
1512
1706
  this.sink.setNodeValue(PIN_ATTRIBUTE, index, true);
1513
1707
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
- * The DOT / Graphviz subpath entry (`@graphty/graph-io/dot`, design section 8.2): the importer and
2
+ * The DOT / Graphviz subpath entry (`@graphty/graph-io/dot`): the importer and
3
3
  * exporter plugins with their option types and issue / loss codes.
4
+ * @module @graphty/graph-io/dot
4
5
  */
5
6
 
6
7
  export { DOT_LOSS, dotExporter, type DotExportOptions } from "./exporter.js";
@@ -6,35 +6,68 @@
6
6
 
7
7
  import { type ColumnOriginInput } from "@graphty/graph-format";
8
8
 
9
- /** The format name. */
9
+ /**
10
+ * The format name.
11
+ * @category Plugin helpers
12
+ */
10
13
  export const DOT_FORMAT = "dot";
11
14
 
12
- /** The origin recorded on every column the importer declares. */
15
+ /**
16
+ * The origin recorded on every column the importer declares.
17
+ * @category Plugin helpers
18
+ */
13
19
  export const DOT_ORIGIN: ColumnOriginInput = Object.freeze({ format: DOT_FORMAT });
14
20
 
15
- /** The bool node column marking a cluster's container node. */
21
+ /**
22
+ * The bool node column marking a cluster's container node.
23
+ * @category Plugin helpers
24
+ */
16
25
  export const CLUSTER_COLUMN = "graphty.cluster";
17
26
 
18
- /** The u32 node column (role parent, refersTo node) holding a member's cluster. */
27
+ /**
28
+ * The u32 node column (role parent, refersTo node) holding a member's cluster.
29
+ * @category Plugin helpers
30
+ */
19
31
  export const PARENT_COLUMN = "graphty.parent";
20
32
 
21
- /** The string edge column (role sourcePort) holding an edge's tail port. */
33
+ /**
34
+ * The string edge column (role sourcePort) holding an edge's tail port.
35
+ * @category Plugin helpers
36
+ */
22
37
  export const SOURCE_PORT_COLUMN = "graphty.sourcePort";
23
38
 
24
- /** The string edge column (role targetPort) holding an edge's head port. */
39
+ /**
40
+ * The string edge column (role targetPort) holding an edge's head port.
41
+ * @category Plugin helpers
42
+ */
25
43
  export const TARGET_PORT_COLUMN = "graphty.targetPort";
26
44
 
27
- /** The attribute that is the display label (kept as text with role label). */
45
+ /**
46
+ * The attribute that is the display label (kept as text with role label).
47
+ * @category Plugin helpers
48
+ */
28
49
  export const LABEL_ATTRIBUTE = "label";
29
50
 
30
- /** The node attribute holding a position, mapped to the position role column (design section 5.2). */
51
+ /**
52
+ * The node attribute holding a position, mapped to the position role column (design section 5.2).
53
+ * @category Plugin helpers
54
+ */
31
55
  export const POS_ATTRIBUTE = "pos";
32
56
 
33
- /** The edge attribute cgraph uses as an edge's identity within its endpoints, mapped to the edge id role. */
57
+ /**
58
+ * The edge attribute cgraph uses as an edge's identity within its endpoints, mapped to the edge id role.
59
+ * @category Plugin helpers
60
+ */
34
61
  export const KEY_ATTRIBUTE = "key";
35
62
 
36
- /** The node attribute a `!` suffix of `pos` sets (Graphviz's own spelling of a pinned position). */
63
+ /**
64
+ * The node attribute a `!` suffix of `pos` sets (Graphviz's own spelling of a pinned position).
65
+ * @category Plugin helpers
66
+ */
37
67
  export const PIN_ATTRIBUTE = "pin";
38
68
 
39
- /** The key under meta.extra holding the format's graph flags (`{ strict: true }`). */
69
+ /**
70
+ * The key under meta.extra holding the format's graph flags (`{ strict: true }`).
71
+ * @category Plugin helpers
72
+ */
40
73
  export const DOT_META_KEY = "dot";