@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
@@ -27,50 +27,72 @@
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
  */
34
- import { type GraphImporter } from "../../types.js";
35
- /** The DOT importer's format-specific options. */
36
- export interface DotImportOptions {
34
+ import { type CommonImportOptions, type GraphChoiceOptions, type GraphImporter } from "../../types.js";
35
+ /**
36
+ * The DOT importer's format-specific options.
37
+ * @category Built-in formats
38
+ */
39
+ export interface DotImportOptions extends GraphChoiceOptions, CommonImportOptions {
37
40
  /**
38
41
  * What an edge operator that contradicts the graph keyword means (`--` in a digraph, `->` in a
39
- * graph; a syntax error for Graphviz): "operator" (default) reads the edge with the operator's
40
- * direction and resolves it per onMixedDirection, with a warning; "header" reads it with the
41
- * graph's direction, with a warning; "error" aborts the import as Graphviz does.
42
+ * graph; Graphviz refuses such a file): "operator" reads the edge with the operator's
43
+ * direction, so the graph has both directions and `onMixedDirection` decides, with a warning;
44
+ * "header" reads it with the graph's direction, with a warning; "error" stops the import with an
45
+ * ImportError whose `issue.code` is E_SYNTAX, as Graphviz does.
46
+ * @defaultValue "operator"
42
47
  */
43
48
  mismatchedEdgeOperator?: "operator" | "header" | "error" | undefined;
44
49
  /**
45
- * Map a node's `pos` to a `pos` column with the position role and a trailing `!` to `pin`
46
- * (default true); false keeps `pos` as the text the file wrote, like any other attribute.
50
+ * Read a node's `pos` attribute as its position (a trailing `!` becomes a `pin` attribute);
51
+ * false keeps `pos` as the text the file wrote, like any other attribute.
52
+ * @defaultValue true
47
53
  */
48
54
  positions?: boolean | undefined;
49
55
  }
50
56
  /**
51
- * The issue codes the DOT importer records (design section 8.6), by name: the codes shared with
52
- * the other importers (src/common/codes.ts) and the DOT-specific ones. A key is the code without
57
+ * The issue codes the DOT importer records, by name: the codes shared with
58
+ * the other importers and the DOT-specific ones. A key is the code without
53
59
  * its severity and format prefixes.
60
+ * @category Built-in formats
54
61
  */
55
62
  export declare const DOT_ISSUE: Readonly<{
56
- /** A grammar violation; fatal. */
63
+ /** The text breaks DOT's syntax; the message says where. The import stops. */
57
64
  SYNTAX: "E_SYNTAX";
58
- /** The input holds no graph at all (empty or only comments); fatal. */
65
+ /** The input holds no graph: it is empty or only comments. The import stops. */
59
66
  EMPTY_INPUT: "E_EMPTY_INPUT";
60
- /** The input holds invalid UTF-8 (fatal). */
67
+ /** The input is not valid UTF-8. The import stops. */
61
68
  INVALID_UTF8: "E_INVALID_UTF8";
62
- /** Invalid bytes in the encoding a BOM, a declaration or the encoding option chose (fatal). */
69
+ /**
70
+ * Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
71
+ * `encoding` option). The import stops.
72
+ */
63
73
  INVALID_ENCODING: "E_INVALID_ENCODING";
64
74
  /** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
65
75
  ENCODING_FALLBACK: "W_ENCODING_FALLBACK";
66
76
  /** A declared encoding the platform cannot decode was ignored. */
67
77
  UNKNOWN_ENCODING: "W_UNKNOWN_ENCODING";
68
- /** Subgraphs or braces nested deeper than the parser's limit; fatal. */
78
+ /** A declared encoding the byte order mark contradicts (the mark wins). */
79
+ ENCODING_CONFLICT: "W_ENCODING_CONFLICT";
80
+ /** Subgraphs or braces are nested deeper than graph-io reads. The import stops. */
69
81
  NESTING: "E_DOT_NESTING";
70
- /** An edge operator contradicting the graph keyword (warning under "operator" / "header"). */
82
+ /**
83
+ * An edge operator contradicting the graph keyword, read under mismatchedEdgeOperator "operator" or "header".
84
+ * Under "error" the import stops with E_SYNTAX instead.
85
+ */
71
86
  EDGE_OPERATOR: "W_DOT_EDGE_OPERATOR";
72
- /** A second graph in the same input; only the first is read. */
87
+ /**
88
+ * The file holds several graphs and only the first was read. It is not added when `graphIndex` or `graphName` chose the graph.
89
+ * `importAllGraphs()` reads every one.
90
+ */
73
91
  MULTIPLE_GRAPHS: "W_MULTIPLE_GRAPHS";
92
+ /** `graphIndex` or `graphName` names no graph of the file; the message lists the graphs it holds. The import stops. */
93
+ GRAPH_NOT_FOUND: "E_GRAPH_NOT_FOUND";
94
+ /** `graphName` matches more than one graph; pass `graphIndex`. The import stops. */
95
+ AMBIGUOUS_GRAPH_NAME: "E_AMBIGUOUS_GRAPH_NAME";
74
96
  /** A badly delimited numeral (`1e3`) split into two tokens, as Graphviz does with a warning. */
75
97
  NUMERAL_AMBIGUITY: "W_DOT_NUMERAL_AMBIGUITY";
76
98
  /** Attributes of a subgraph that is not a cluster (rank=same and the like) cannot be represented. */
@@ -81,33 +103,73 @@ export declare const DOT_ISSUE: Readonly<{
81
103
  CLUSTER_NODE_MERGED: "W_DOT_CLUSTER_NODE_MERGED";
82
104
  /** A node mentioned in two unrelated clusters keeps the first. */
83
105
  CLUSTER_CONFLICT: "W_DOT_CLUSTER_CONFLICT";
84
- /** A node `pos` that is not a point; the value was dropped. */
106
+ /** A node's `pos` is not a point, or is too large for a 32-bit float position; the value was dropped. */
85
107
  BAD_POS: "W_DOT_BAD_POS";
108
+ /** Node `pos` values mix two and three coordinates; the position column records the first's. */
109
+ POS_DIMS: "W_DOT_POS_DIMS";
110
+ /** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
111
+ PRECISION: "W_PRECISION";
112
+ /** The same attribute twice in one statement's attribute lists; the last value stands, as in Graphviz. */
113
+ DUPLICATE_ATTRIBUTE: "W_DUPLICATE_ATTRIBUTE";
114
+ /** The second part of a port (`a:p:zz`) is not a compass point; kept as written, as Graphviz warns. */
115
+ COMPASS_POINT: "W_DOT_COMPASS_POINT";
116
+ /** A `charset` attribute beyond the head the decoder reads it from; the input was decoded without it. */
117
+ LATE_CHARSET: "W_DOT_LATE_CHARSET";
86
118
  /** A parallel edge merged into an earlier one under `strict`. */
87
119
  STRICT_MERGED: "W_DOT_STRICT_MERGED";
88
120
  /** An edge merged into an earlier one with the same endpoints and `key`. */
89
121
  KEY_MERGED: "W_DOT_KEY_MERGED";
90
- /** A role (label, id, position, ...) was already taken in the caller's sink; the column was declared without it. */
122
+ /**
123
+ * You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
124
+ * a plain attribute.
125
+ */
91
126
  ROLE_TAKEN: "W_ROLE_TAKEN";
92
- /** A column of another shape exists in the caller's sink under a name the importer declares; renamed `<name>#<id>`. */
127
+ /**
128
+ * An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example
129
+ * two attributes declared with the same name.
130
+ */
93
131
  COLUMN_RENAMED: "W_COLUMN_RENAMED";
94
- /** A common option the format has no use for was given a non-default value. */
132
+ /** You set an option this format does not use; it had no effect. The message names the option. */
95
133
  OPTION_IGNORED: "W_OPTION_IGNORED";
96
- /** Two distinct id texts merged under ids: "number". */
134
+ /** Two different id texts became the same number because `ids` is "number", so their nodes were merged. */
97
135
  ID_MERGED: "W_ID_MERGED";
98
- /** A builder-policy option the sink does not honour. */
136
+ /**
137
+ * You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
138
+ * `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
139
+ */
99
140
  SINK_OPTION: "W_SINK_OPTION";
100
- /** The sink refused the file's direction. */
141
+ /**
142
+ * You read into a graph builder whose direction is already set, or which already holds edges, so the file is read
143
+ * with the builder's direction instead of its own.
144
+ */
101
145
  DIRECTION_REFUSED: "W_DIRECTION_REFUSED";
102
- /** Edges forced to the policy's direction. */
146
+ /** Edges of the other direction were read with the direction `onMixedDirection` chose. */
103
147
  DIRECTION_FORCED: "W_DIRECTION_FORCED";
104
- /** A mixed file under onMixedDirection "error" (fatal). */
148
+ /**
149
+ * The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
150
+ * format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
151
+ * it anyway.
152
+ */
105
153
  MIXED_DIRECTION: "E_MIXED_DIRECTION";
106
- /** A text column the sink could not widen to the dtype its cells imply. */
154
+ /**
155
+ * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of
156
+ * its first values.
157
+ */
107
158
  WIDENING_UNSUPPORTED: "W_WIDENING_UNSUPPORTED";
159
+ INVALID_ID: "E_INVALID_ID";
160
+ UNKNOWN_NODE: "E_UNKNOWN_NODE";
161
+ INVALID_WEIGHT: "E_INVALID_WEIGHT";
162
+ DUPLICATE_EDGE: "E_DUPLICATE_EDGE";
163
+ SELF_LOOP: "E_SELF_LOOP";
164
+ DUPLICATE_EDGE_ID: "E_DUPLICATE_EDGE_ID";
165
+ TOO_LARGE: "E_TOO_LARGE";
166
+ CONTROL_CHARACTER: "W_CONTROL_CHARACTER";
167
+ FOREIGN_FORMAT: "E_FOREIGN_FORMAT";
168
+ ISSUES_SUPPRESSED: "W_ISSUES_SUPPRESSED";
108
169
  }>;
109
170
  /**
110
- * The importer plugin for DOT / Graphviz text (design section 12.4).
171
+ * The importer plugin for DOT / Graphviz text.
172
+ * @category Built-in formats
111
173
  */
112
174
  export declare const dotImporter: GraphImporter<DotImportOptions>;
113
175
  //# sourceMappingURL=importer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../../../src/formats/dot/importer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAyCH,OAAO,EAA4B,KAAK,aAAa,EAAuC,MAAM,gBAAgB,CAAC;AAenH,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC7B;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IACrE;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS;IAClB,kCAAkC;;IAElC,uEAAuE;;IAEvE,6CAA6C;;IAE7C,+FAA+F;;IAE/F,kFAAkF;;IAElF,kEAAkE;;IAElE,wEAAwE;;IAExE,8FAA8F;;IAE9F,gEAAgE;;IAEhE,gGAAgG;;IAEhG,qGAAqG;;IAErG,iEAAiE;;IAEjE,uFAAuF;;IAEvF,kEAAkE;;IAElE,+DAA+D;;IAE/D,iEAAiE;;IAEjE,4EAA4E;;IAE5E,oHAAoH;;IAEpH,uHAAuH;;IAEvH,+EAA+E;;IAE/E,wDAAwD;;IAExD,wDAAwD;;IAExD,6CAA6C;;IAE7C,8CAA8C;;IAE9C,2DAA2D;;IAE3D,2EAA2E;;EAE7E,CAAC;AA8EH;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAwGtD,CAAC"}
1
+ {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../../../src/formats/dot/importer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAoDH,OAAO,EACH,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAGrB,MAAM,gBAAgB,CAAC;AAexB;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB,EAAE,mBAAmB;IAC7E;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IACrE;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS;IAGlB,8EAA8E;;IAE9E,gFAAgF;;IAEhF,sDAAsD;;IAEtD;;;OAGG;;IAEH,kFAAkF;;IAElF,kEAAkE;;IAElE,2EAA2E;;IAE3E,mFAAmF;;IAEnF;;;OAGG;;IAEH;;;OAGG;;IAEH,uHAAuH;;IAEvH,oFAAoF;;IAEpF,gGAAgG;;IAEhG,qGAAqG;;IAErG,iEAAiE;;IAEjE,uFAAuF;;IAEvF,kEAAkE;;IAElE,yGAAyG;;IAEzG,gGAAgG;;IAEhG,gHAAgH;;IAEhH,0GAA0G;;IAE1G,uGAAuG;;IAEvG,yGAAyG;;IAGzG,iEAAiE;;IAEjE,4EAA4E;;IAE5E;;;OAGG;;IAEH;;;OAGG;;IAEH,kGAAkG;;IAElG,2GAA2G;;IAE3G;;;OAGG;;IAEH;;;OAGG;;IAEH,0FAA0F;;IAE1F;;;;OAIG;;IAEH;;;OAGG;;;;;;;;;;;;EAEL,CAAC;AAuFH;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAoHtD,CAAC"}
@@ -27,46 +27,67 @@
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
  */
34
34
  import { GraphFormatError, INVALID_INDEX, } from "@graphty/graph-format";
35
35
  import { declareResolved } from "../../common/attributes.js";
36
- import { COLUMN_RENAMED_CODE, DIRECTION_FORCED_CODE, DIRECTION_REFUSED_CODE, EMPTY_INPUT_CODE, ENCODING_FALLBACK_CODE, ID_MERGED_CODE, INVALID_ENCODING_CODE, INVALID_UTF8_CODE, MIXED_DIRECTION_CODE, MULTIPLE_GRAPHS_CODE, OPTION_IGNORED_CODE, ROLE_TAKEN_CODE, SINK_OPTION_CODE, SYNTAX_CODE, UNKNOWN_ENCODING_CODE, } from "../../common/codes.js";
36
+ import { importChosenGraph } from "../../common/choose.js";
37
+ import { AMBIGUOUS_GRAPH_NAME_CODE, COLUMN_RENAMED_CODE, DIRECTION_FORCED_CODE, DIRECTION_REFUSED_CODE, DUPLICATE_ATTRIBUTE_CODE, ELEMENT_ISSUE, EMPTY_INPUT_CODE, ENCODING_CONFLICT_CODE, ENCODING_FALLBACK_CODE, GRAPH_NOT_FOUND_CODE, ID_MERGED_CODE, INPUT_ISSUE, INVALID_ENCODING_CODE, INVALID_UTF8_CODE, MIXED_DIRECTION_CODE, MULTIPLE_GRAPHS_CODE, OPTION_IGNORED_CODE, PRECISION_CODE, ROLE_TAKEN_CODE, SINK_OPTION_CODE, SYNTAX_CODE, UNKNOWN_ENCODING_CODE, } from "../../common/codes.js";
37
38
  import { DirectionResolver } from "../../common/direction.js";
39
+ import { survivesF32 } from "../../common/format.js";
38
40
  import { IdCoercer } from "../../common/ids.js";
39
- import { readText, throwIfAborted } from "../../common/input.js";
40
- import { reportSinkOptions, reportUnusedOptions, resolveImportOptions, } from "../../common/options.js";
41
+ import { canonicalEncoding, readText, throwIfAborted } from "../../common/input.js";
42
+ import { graphChosen, reportSinkOptions, reportUnusedOptions, resolveImportOptions, } from "../../common/options.js";
43
+ import { plural } from "../../common/plural.js";
41
44
  import { ImportReportBuilder } from "../../common/report.js";
42
45
  import { inferTextDtype, parseTextCell, TextCellWriter, WIDENING_UNSUPPORTED_CODE } from "../../common/text.js";
43
46
  import { parseWeightText } from "../../common/weights.js";
44
47
  import { CLUSTER_COLUMN, DOT_FORMAT, DOT_ORIGIN, KEY_ATTRIBUTE, LABEL_ATTRIBUTE, PARENT_COLUMN, PIN_ATTRIBUTE, POS_ATTRIBUTE, SOURCE_PORT_COLUMN, TARGET_PORT_COLUMN, } from "./names.js";
45
48
  import { DotSyntaxError, DotTokenizer } from "./tokenizer.js";
46
49
  /**
47
- * The issue codes the DOT importer records (design section 8.6), by name: the codes shared with
48
- * the other importers (src/common/codes.ts) and the DOT-specific ones. A key is the code without
50
+ * The issue codes the DOT importer records, by name: the codes shared with
51
+ * the other importers and the DOT-specific ones. A key is the code without
49
52
  * its severity and format prefixes.
53
+ * @category Built-in formats
50
54
  */
51
55
  export const DOT_ISSUE = Object.freeze({
52
- /** A grammar violation; fatal. */
56
+ ...INPUT_ISSUE,
57
+ ...ELEMENT_ISSUE,
58
+ /** The text breaks DOT's syntax; the message says where. The import stops. */
53
59
  SYNTAX: SYNTAX_CODE,
54
- /** The input holds no graph at all (empty or only comments); fatal. */
60
+ /** The input holds no graph: it is empty or only comments. The import stops. */
55
61
  EMPTY_INPUT: EMPTY_INPUT_CODE,
56
- /** The input holds invalid UTF-8 (fatal). */
62
+ /** The input is not valid UTF-8. The import stops. */
57
63
  INVALID_UTF8: INVALID_UTF8_CODE,
58
- /** Invalid bytes in the encoding a BOM, a declaration or the encoding option chose (fatal). */
64
+ /**
65
+ * Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
66
+ * `encoding` option). The import stops.
67
+ */
59
68
  INVALID_ENCODING: INVALID_ENCODING_CODE,
60
69
  /** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
61
70
  ENCODING_FALLBACK: ENCODING_FALLBACK_CODE,
62
71
  /** A declared encoding the platform cannot decode was ignored. */
63
72
  UNKNOWN_ENCODING: UNKNOWN_ENCODING_CODE,
64
- /** Subgraphs or braces nested deeper than the parser's limit; fatal. */
73
+ /** A declared encoding the byte order mark contradicts (the mark wins). */
74
+ ENCODING_CONFLICT: ENCODING_CONFLICT_CODE,
75
+ /** Subgraphs or braces are nested deeper than graph-io reads. The import stops. */
65
76
  NESTING: "E_DOT_NESTING",
66
- /** An edge operator contradicting the graph keyword (warning under "operator" / "header"). */
77
+ /**
78
+ * An edge operator contradicting the graph keyword, read under mismatchedEdgeOperator "operator" or "header".
79
+ * Under "error" the import stops with E_SYNTAX instead.
80
+ */
67
81
  EDGE_OPERATOR: "W_DOT_EDGE_OPERATOR",
68
- /** A second graph in the same input; only the first is read. */
82
+ /**
83
+ * The file holds several graphs and only the first was read. It is not added when `graphIndex` or `graphName` chose the graph.
84
+ * `importAllGraphs()` reads every one.
85
+ */
69
86
  MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
87
+ /** `graphIndex` or `graphName` names no graph of the file; the message lists the graphs it holds. The import stops. */
88
+ GRAPH_NOT_FOUND: GRAPH_NOT_FOUND_CODE,
89
+ /** `graphName` matches more than one graph; pass `graphIndex`. The import stops. */
90
+ AMBIGUOUS_GRAPH_NAME: AMBIGUOUS_GRAPH_NAME_CODE,
70
91
  /** A badly delimited numeral (`1e3`) split into two tokens, as Graphviz does with a warning. */
71
92
  NUMERAL_AMBIGUITY: "W_DOT_NUMERAL_AMBIGUITY",
72
93
  /** Attributes of a subgraph that is not a cluster (rank=same and the like) cannot be represented. */
@@ -77,29 +98,58 @@ export const DOT_ISSUE = Object.freeze({
77
98
  CLUSTER_NODE_MERGED: "W_DOT_CLUSTER_NODE_MERGED",
78
99
  /** A node mentioned in two unrelated clusters keeps the first. */
79
100
  CLUSTER_CONFLICT: "W_DOT_CLUSTER_CONFLICT",
80
- /** A node `pos` that is not a point; the value was dropped. */
101
+ /** A node's `pos` is not a point, or is too large for a 32-bit float position; the value was dropped. */
81
102
  BAD_POS: "W_DOT_BAD_POS",
103
+ /** Node `pos` values mix two and three coordinates; the position column records the first's. */
104
+ POS_DIMS: "W_DOT_POS_DIMS",
105
+ /** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
106
+ PRECISION: PRECISION_CODE,
107
+ /** The same attribute twice in one statement's attribute lists; the last value stands, as in Graphviz. */
108
+ DUPLICATE_ATTRIBUTE: DUPLICATE_ATTRIBUTE_CODE,
109
+ /** The second part of a port (`a:p:zz`) is not a compass point; kept as written, as Graphviz warns. */
110
+ COMPASS_POINT: "W_DOT_COMPASS_POINT",
111
+ /** A `charset` attribute beyond the head the decoder reads it from; the input was decoded without it. */
112
+ LATE_CHARSET: "W_DOT_LATE_CHARSET",
82
113
  /** A parallel edge merged into an earlier one under `strict`. */
83
114
  STRICT_MERGED: "W_DOT_STRICT_MERGED",
84
115
  /** An edge merged into an earlier one with the same endpoints and `key`. */
85
116
  KEY_MERGED: "W_DOT_KEY_MERGED",
86
- /** A role (label, id, position, ...) was already taken in the caller's sink; the column was declared without it. */
117
+ /**
118
+ * You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
119
+ * a plain attribute.
120
+ */
87
121
  ROLE_TAKEN: ROLE_TAKEN_CODE,
88
- /** A column of another shape exists in the caller's sink under a name the importer declares; renamed `<name>#<id>`. */
122
+ /**
123
+ * An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example
124
+ * two attributes declared with the same name.
125
+ */
89
126
  COLUMN_RENAMED: COLUMN_RENAMED_CODE,
90
- /** A common option the format has no use for was given a non-default value. */
127
+ /** You set an option this format does not use; it had no effect. The message names the option. */
91
128
  OPTION_IGNORED: OPTION_IGNORED_CODE,
92
- /** Two distinct id texts merged under ids: "number". */
129
+ /** Two different id texts became the same number because `ids` is "number", so their nodes were merged. */
93
130
  ID_MERGED: ID_MERGED_CODE,
94
- /** A builder-policy option the sink does not honour. */
131
+ /**
132
+ * You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
133
+ * `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
134
+ */
95
135
  SINK_OPTION: SINK_OPTION_CODE,
96
- /** The sink refused the file's direction. */
136
+ /**
137
+ * You read into a graph builder whose direction is already set, or which already holds edges, so the file is read
138
+ * with the builder's direction instead of its own.
139
+ */
97
140
  DIRECTION_REFUSED: DIRECTION_REFUSED_CODE,
98
- /** Edges forced to the policy's direction. */
141
+ /** Edges of the other direction were read with the direction `onMixedDirection` chose. */
99
142
  DIRECTION_FORCED: DIRECTION_FORCED_CODE,
100
- /** A mixed file under onMixedDirection "error" (fatal). */
143
+ /**
144
+ * The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
145
+ * format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
146
+ * it anyway.
147
+ */
101
148
  MIXED_DIRECTION: MIXED_DIRECTION_CODE,
102
- /** A text column the sink could not widen to the dtype its cells imply. */
149
+ /**
150
+ * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of
151
+ * its first values.
152
+ */
103
153
  WIDENING_UNSUPPORTED: WIDENING_UNSUPPORTED_CODE,
104
154
  });
105
155
  /** The common options the DOT importer reads (the rest is reported by reportUnusedOptions). */
@@ -129,12 +179,22 @@ const MAX_ANCESTOR_WALK = 4096;
129
179
  */
130
180
  const DOT_HEADER = /^\s*(strict\s+)?(di)?graph(?=[\s{"/]|$)(?!\s*\[)/i;
131
181
  const TRUE_TEXTS = new Set(["true", "yes", "1"]);
132
- const POINT_TEXT = /^\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*$/;
182
+ const COMPASS_POINTS = new Set(["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "_"]);
133
183
  /**
134
- * The importer plugin for DOT / Graphviz text (design section 12.4).
184
+ * A DOT number: digits with an optional fraction, or a bare fraction (`.5`), then an exponent.
185
+ * Written so each digit has exactly one way to match; `[0-9]*\.?[0-9]+` took quadratic time on a
186
+ * long run of digits.
187
+ */
188
+ const POINT_NUMBER = String.raw `[-+]?(?:\d+(?:\.\d+)?|\.\d+)(?:[eE][-+]?\d+)?`;
189
+ /** A point "x,y[,z][!]". The `!` and its trailing space are one optional group, so spaces cannot split two ways. */
190
+ const POINT_TEXT = new RegExp(String.raw `^\s*(${POINT_NUMBER})\s*,\s*(${POINT_NUMBER})(?:\s*,\s*(${POINT_NUMBER}))?\s*(?:(!)\s*)?$`);
191
+ /**
192
+ * The importer plugin for DOT / Graphviz text.
193
+ * @category Built-in formats
135
194
  */
136
195
  export const dotImporter = Object.freeze({
137
196
  format: DOT_FORMAT,
197
+ options: Object.freeze(["mismatchedEdgeOperator", "positions"]),
138
198
  extensions: EXTENSIONS,
139
199
  mimeTypes: MIME_TYPES,
140
200
  /**
@@ -159,6 +219,10 @@ export const dotImporter = Object.freeze({
159
219
  * @returns the import report; ImportError (E_IMPORT) on a syntax error or beyond the error limit
160
220
  */
161
221
  async import(input, sink, options) {
222
+ if (graphChosen(options)) {
223
+ // the choice is honored here too, not only by the registry
224
+ return importChosenGraph(dotImporter, input, sink, options);
225
+ }
162
226
  const resolved = resolveImportOptions(options, {
163
227
  ids: "canonical",
164
228
  defaultDirected: true,
@@ -168,14 +232,22 @@ export const dotImporter = Object.freeze({
168
232
  const report = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
169
233
  reportUnusedOptions(options, report, USED_OPTIONS);
170
234
  reportSinkOptions(sink, options, report);
171
- const text = await readText(input, report, { ...resolved, declaredEncoding: dotCharset });
235
+ const head = {};
236
+ const text = await readText(input, report, {
237
+ ...resolved,
238
+ declaredEncoding: (h) => (head.charset = dotCharset(h)),
239
+ declarationBytes: CHARSET_HEAD_BYTES,
240
+ });
172
241
  const reports = { current: report };
173
242
  const lexer = dotLexer(text, reports);
174
243
  const first = guard(report, () => lexer.next());
175
- const trailing = parseGraph(new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false), report, first);
244
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
245
+ parser.headCharset = head.charset;
246
+ const trailing = parseGraph(parser, report, first);
176
247
  if (trailing.kind !== "eof") {
248
+ // anything after the graph must be graphs too: Graphviz refuses the file otherwise
177
249
  const skipped = guard(report, () => countGraphs(lexer, trailing));
178
- report.warning("unsupported", MULTIPLE_GRAPHS_CODE, `the input holds ${skipped} more graph(s) after the first; import() reads the first, importAll() reads every one`, { line: trailing.line });
250
+ report.warning("unsupported", MULTIPLE_GRAPHS_CODE, `the input holds ${skipped} more graph${plural(skipped)} after the first; the first is read (graphIndex or graphName chooses another; importAllGraphs() reads every one)`, { line: trailing.line });
179
251
  }
180
252
  // an abort raised during the last few statements (after the last periodic check) still rejects
181
253
  throwIfAborted(resolved.signal);
@@ -197,7 +269,12 @@ export const dotImporter = Object.freeze({
197
269
  const mismatch = mismatchOption(options?.mismatchedEdgeOperator);
198
270
  const first = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
199
271
  reportUnusedOptions(options, first, USED_OPTIONS);
200
- const text = await readText(input, first, { ...resolved, declaredEncoding: dotCharset });
272
+ const head = {};
273
+ const text = await readText(input, first, {
274
+ ...resolved,
275
+ declaredEncoding: (h) => (head.charset = dotCharset(h)),
276
+ declarationBytes: CHARSET_HEAD_BYTES,
277
+ });
201
278
  const reports = { current: first };
202
279
  const lexer = dotLexer(text, reports);
203
280
  const done = [];
@@ -207,7 +284,9 @@ export const dotImporter = Object.freeze({
207
284
  reports.current = report;
208
285
  const sink = sinkFor(done.length);
209
286
  reportSinkOptions(sink, options, report);
210
- token = parseGraph(new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false), report, token);
287
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
288
+ parser.headCharset = head.charset;
289
+ token = parseGraph(parser, report, token);
211
290
  throwIfAborted(resolved.signal);
212
291
  done.push(report.finish());
213
292
  } while (token.kind !== "eof");
@@ -268,6 +347,9 @@ function countGraphs(lexer, first) {
268
347
  if (isKeyword(token, "strict")) {
269
348
  token = lexer.next();
270
349
  }
350
+ if (isPunct(token, "}")) {
351
+ throw new DotSyntaxError('unexpected "}" after the end of the graph: no "{" is open', token.line);
352
+ }
271
353
  if (!isKeyword(token, "graph") && !isKeyword(token, "digraph")) {
272
354
  throw new DotSyntaxError(`expected "graph" or "digraph", found ${describeToken(token)}`, token.line);
273
355
  }
@@ -295,18 +377,49 @@ function countGraphs(lexer, first) {
295
377
  }
296
378
  return count;
297
379
  }
298
- /** A `charset` attribute assignment (Graphviz's declaration of the input encoding). */
299
- const DOT_CHARSET = /\bcharset\s*=\s*"?([A-Za-z][A-Za-z0-9._-]*)/i;
380
+ /** How many leading bytes the `charset` search sees: a license comment may come before the graph. */
381
+ const CHARSET_HEAD_BYTES = 64 * 1024;
300
382
  /**
301
383
  * The encoding a DOT file declares with the graph attribute `charset` (Graphviz reads UTF-8,
302
384
  * Latin1 and Big-5), for the shared byte decoder; Graphviz's spellings `latin-1` and `big-5` are
303
- * mapped to the WHATWG labels.
385
+ * mapped to the WHATWG labels. Only a graph-level assignment counts (`charset=...` as a statement
386
+ * or inside `graph [...]`), never one in a comment, a quoted value or a node / edge attribute list.
304
387
  * @param head - the start of the file, decoded as windows-1252
305
388
  * @returns the declared label, or null
306
389
  */
307
390
  function dotCharset(head) {
308
- const match = DOT_CHARSET.exec(head);
309
- return match === null ? null : match[1].replace(/^(latin|big)-/i, "$1");
391
+ const lexer = new DotTokenizer(head);
392
+ // the attribute list an open `[` belongs to: the graph's (`graph [`) or a node's / an edge's
393
+ let list = null;
394
+ let previous = null;
395
+ try {
396
+ let token = lexer.next();
397
+ while (token.kind !== "eof") {
398
+ if (isPunct(token, "[")) {
399
+ list = previous !== null && isKeyword(previous, "graph") ? "graph" : "other";
400
+ }
401
+ else if (isPunct(token, "]")) {
402
+ list = null;
403
+ }
404
+ else if (list !== "other" && isKeyword(token, "charset")) {
405
+ const equals = lexer.next();
406
+ const value = isPunct(equals, "=") ? lexer.next() : equals;
407
+ if (value !== equals && value.kind === "id") {
408
+ return value.text.replace(/^(latin|big)-/i, "$1");
409
+ }
410
+ token = value;
411
+ }
412
+ previous = token;
413
+ token = lexer.next();
414
+ }
415
+ }
416
+ catch (err) {
417
+ // the head ends inside a comment or a string: nothing further is seen
418
+ if (!(err instanceof DotSyntaxError)) {
419
+ throw err;
420
+ }
421
+ }
422
+ return null;
310
423
  }
311
424
  /**
312
425
  * Resolve the mismatchedEdgeOperator option.
@@ -435,6 +548,14 @@ class DotParser {
435
548
  this.targetPortHandle = INVALID_INDEX;
436
549
  /** The current subgraph nesting depth. */
437
550
  this.depth = 0;
551
+ /** The coordinate count of the first `pos`, or 0 before one. */
552
+ this.posDims = 0;
553
+ /**
554
+ * What the decoder's look at the head found for `charset`: a label, null for none, undefined
555
+ * when it never looked (text input, a BOM, the encoding option). A `charset` assignment read
556
+ * when the head had none came too late to decode by.
557
+ */
558
+ this.headCharset = undefined;
438
559
  /** The inferred attribute columns by name, per domain (the 5.1 text grammar per column). */
439
560
  this.nodeWriters = new Map();
440
561
  this.edgeWriters = new Map();
@@ -627,7 +748,11 @@ class DotParser {
627
748
  let { text } = this.identifier();
628
749
  if (isPunct(lexer.peek(), ":")) {
629
750
  lexer.next();
630
- text += `:${this.identifier().text}`;
751
+ const compass = this.identifier();
752
+ text += `:${compass.text}`;
753
+ if (!COMPASS_POINTS.has(compass.text)) {
754
+ this.report.warning("validation-error", DOT_ISSUE.COMPASS_POINT, `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`, { line: compass.line, element: text });
755
+ }
631
756
  }
632
757
  return text;
633
758
  }
@@ -853,6 +978,7 @@ class DotParser {
853
978
  attributeList() {
854
979
  const { lexer } = this;
855
980
  const out = [];
981
+ const names = new Set();
856
982
  while (isPunct(lexer.peek(), "[")) {
857
983
  lexer.next();
858
984
  for (;;) {
@@ -871,6 +997,10 @@ class DotParser {
871
997
  throw new DotSyntaxError(`expected "=" after attribute name ${JSON.stringify(name.text)}, found ${describeToken(eq)}`, eq.line);
872
998
  }
873
999
  const value = this.identifier();
1000
+ if (names.has(name.text)) {
1001
+ this.report.warning("merged", DOT_ISSUE.DUPLICATE_ATTRIBUTE, `attribute ${JSON.stringify(name.text)} is set twice in one statement; the last value ${JSON.stringify(value.text)} stands`, { line: name.line, element: name.text });
1002
+ }
1003
+ names.add(name.text);
874
1004
  out.push({ name: name.text, value: value.text, line: name.line });
875
1005
  }
876
1006
  }
@@ -957,7 +1087,7 @@ class DotParser {
957
1087
  this.report.warnOnce("coercion", DOT_ISSUE.EDGE_OPERATOR, `${message}; read with the graph's direction (mismatchedEdgeOperator: "header")`, { line: op.line });
958
1088
  return this.directed ? "directed" : "undirected";
959
1089
  case "operator":
960
- this.report.warnOnce("coercion", DOT_ISSUE.EDGE_OPERATOR, `${message}; read with the operator's direction and resolved per onMixedDirection`, { line: op.line });
1090
+ this.report.warnOnce("coercion", DOT_ISSUE.EDGE_OPERATOR, `${message}; read with the operator's direction, and onMixedDirection decides how the mixed graph is stored`, { line: op.line });
961
1091
  return operatorDirected ? "directed" : "undirected";
962
1092
  default: {
963
1093
  const name = this.mismatch;
@@ -1046,7 +1176,7 @@ class DotParser {
1046
1176
  const weightText = weightFrom === null ? undefined : effective.get(weightFrom);
1047
1177
  if (weightText !== undefined) {
1048
1178
  try {
1049
- weight = parseWeightText(weightText);
1179
+ weight = parseWeightText(weightText, this.report);
1050
1180
  }
1051
1181
  catch (err) {
1052
1182
  this.report.recordError(err, where);
@@ -1200,6 +1330,12 @@ class DotParser {
1200
1330
  * @param attribute - the attribute
1201
1331
  */
1202
1332
  setGraphAttribute(attribute) {
1333
+ if (attribute.name.toLowerCase() === "charset" && this.headCharset === null) {
1334
+ const canonical = canonicalEncoding(attribute.value);
1335
+ if (canonical !== "utf-8") {
1336
+ this.report.warning("unsupported", DOT_ISSUE.LATE_CHARSET, `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`, { line: attribute.line, element: attribute.name });
1337
+ }
1338
+ }
1203
1339
  try {
1204
1340
  if (attribute.name === LABEL_ATTRIBUTE) {
1205
1341
  this.sink.setGraphValue(attribute.name, attribute.value, { dtype: "string", origin: DOT_ORIGIN });
@@ -1233,7 +1369,22 @@ class DotParser {
1233
1369
  const y = Number(match[2]);
1234
1370
  const z = match[3] === undefined ? 0 : Number(match[3]);
1235
1371
  const dims = match[3] === undefined ? 2 : 3;
1236
- this.sink.setNodeValue(this.positionColumn(dims), index, [x, y, z]);
1372
+ const point = [x, y, z];
1373
+ if (point.some((v) => !Number.isFinite(Math.fround(v)))) {
1374
+ // the position column is f32: a half-infinite point would be a half-valid position
1375
+ this.report.warning("validation-error", DOT_ISSUE.BAD_POS, `pos ${JSON.stringify(text)} is beyond the f32 range of the position column; dropped`, { line, element });
1376
+ return;
1377
+ }
1378
+ if (!point.every(survivesF32)) {
1379
+ this.report.warnOnce("precision", DOT_ISSUE.PRECISION, `pos ${JSON.stringify(text)} has a coordinate the f32 position column rounds (warned once; positions=false keeps pos as written)`, { line, element }, `${DOT_ISSUE.PRECISION}:pos`);
1380
+ }
1381
+ if (this.posDims === 0) {
1382
+ this.posDims = dims;
1383
+ }
1384
+ else if (dims !== this.posDims) {
1385
+ this.report.warnOnce("validation-error", DOT_ISSUE.POS_DIMS, `pos values mix ${this.posDims} and ${dims} coordinates; the position column records sourceDims ${this.posDims}`, { line, element });
1386
+ }
1387
+ this.sink.setNodeValue(this.positionColumn(dims), index, point);
1237
1388
  if (match[4] === "!") {
1238
1389
  this.sink.setNodeValue(PIN_ATTRIBUTE, index, true);
1239
1390
  }