@graphty/graph-io 0.3.25 → 0.3.27

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-DrXtu_96.js +56 -0
  4. package/dist/chunks/choose-DrXtu_96.js.map +1 -0
  5. package/dist/chunks/constants-ikG85dT8.js +231 -0
  6. package/dist/chunks/constants-ikG85dT8.js.map +1 -0
  7. package/dist/chunks/{escape-B-tkk_Cl.js → escape-D1HPTUrP.js} +390 -99
  8. package/dist/chunks/escape-D1HPTUrP.js.map +1 -0
  9. package/dist/chunks/export-CHd4tQE2.js +4333 -0
  10. package/dist/chunks/export-CHd4tQE2.js.map +1 -0
  11. package/dist/chunks/{importer-eUREhBGj.js → exporter-D23CKNqF.js} +4969 -3201
  12. package/dist/chunks/exporter-D23CKNqF.js.map +1 -0
  13. package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-DfWTgrti.js} +23 -21
  14. package/dist/chunks/exporter-DfWTgrti.js.map +1 -0
  15. package/dist/chunks/exporter-DhtW6FxK.js +3465 -0
  16. package/dist/chunks/exporter-DhtW6FxK.js.map +1 -0
  17. package/dist/chunks/{exporter-BGrsWamJ.js → exporter-IHv4nkCm.js} +38 -229
  18. package/dist/chunks/exporter-IHv4nkCm.js.map +1 -0
  19. package/dist/chunks/{importer-BWY2FFc5.js → importer-B1wmPQjr.js} +255 -77
  20. package/dist/chunks/importer-B1wmPQjr.js.map +1 -0
  21. package/dist/chunks/{importer-D_e7e7LX.js → importer-B2W_58pz.js} +399 -146
  22. package/dist/chunks/importer-B2W_58pz.js.map +1 -0
  23. package/dist/chunks/importer-BSALvkui.js +2811 -0
  24. package/dist/chunks/importer-BSALvkui.js.map +1 -0
  25. package/dist/chunks/{importer-vi3bSdtw.js → importer-BVRE--Un.js} +510 -77
  26. package/dist/chunks/importer-BVRE--Un.js.map +1 -0
  27. package/dist/chunks/{importer-DET1tg6s.js → importer-CIAzt-wo.js} +1689 -312
  28. package/dist/chunks/importer-CIAzt-wo.js.map +1 -0
  29. package/dist/chunks/{importer-DIrbbnAf.js → importer-DpEW5zeG.js} +585 -226
  30. package/dist/chunks/importer-DpEW5zeG.js.map +1 -0
  31. package/dist/chunks/{importer-zGLo8Dg_.js → importer-z_FL4VMb.js} +488 -161
  32. package/dist/chunks/importer-z_FL4VMb.js.map +1 -0
  33. package/dist/chunks/json-elements-BAmNBZok.js +1225 -0
  34. package/dist/chunks/json-elements-BAmNBZok.js.map +1 -0
  35. package/dist/chunks/ontology-export-Bab4eUA8.js +357 -0
  36. package/dist/chunks/ontology-export-Bab4eUA8.js.map +1 -0
  37. package/dist/chunks/{records-dbRkxwaq.js → records-CdlvL4RO.js} +298 -114
  38. package/dist/chunks/records-CdlvL4RO.js.map +1 -0
  39. package/dist/chunks/{text-Dr0Ifpag.js → text-DzXjAiTl.js} +29 -11
  40. package/dist/chunks/text-DzXjAiTl.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 +952 -262
  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 +344 -87
  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 +565 -158
  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 +21 -3
  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 +39 -22
  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 +869 -189
  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 +3 -1
  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 +402 -85
  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 +146 -33
  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 +682 -287
  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 +227 -80
  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 +101 -27
  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 +110 -28
  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 +239 -86
  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 +67 -35
  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 +186 -54
  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 +21 -22
  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 +8 -3
  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 +40 -6
  468. package/src/common/direction.ts +78 -51
  469. package/src/common/escape.ts +39 -22
  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 +1035 -199
  475. package/src/common/line-format.ts +249 -0
  476. package/src/common/lists.ts +7 -2
  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 +479 -90
  487. package/src/common/zip.ts +169 -7
  488. package/src/formats/csv/exporter.ts +202 -47
  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 +890 -302
  496. package/src/formats/cx/index.ts +4 -3
  497. package/src/formats/cx2/exporter.ts +62 -339
  498. package/src/formats/cx2/importer.ts +318 -87
  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 +142 -34
  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 +113 -28
  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 +321 -102
  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 +90 -42
  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 +216 -55
  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 +36 -28
  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 +12 -4
  551. package/src/index.ts +81 -11
  552. package/src/registry.ts +1121 -135
  553. package/src/sniff.ts +163 -32
  554. package/src/types.ts +385 -114
  555. package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
  556. package/dist/chunks/export-Bh60Dv-n.js +0 -582
  557. package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
  558. package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
  559. package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
  560. package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
  561. package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
  562. package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
  563. package/dist/chunks/importer-DET1tg6s.js.map +0 -1
  564. package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
  565. package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
  566. package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
  567. package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
  568. package/dist/chunks/importer-eUREhBGj.js.map +0 -1
  569. package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
  570. package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
  571. package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
  572. package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
  573. package/dist/chunks/ontology-BnrJ4I98.js +0 -113
  574. package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
  575. package/dist/chunks/records-dbRkxwaq.js.map +0 -1
  576. package/dist/chunks/report-B1z4WT9e.js +0 -2372
  577. package/dist/chunks/report-B1z4WT9e.js.map +0 -1
  578. package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
  579. package/dist/chunks/weights-Dzba96G3.js +0 -176
  580. package/dist/chunks/weights-Dzba96G3.js.map +0 -1
  581. package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
@@ -1,11 +1,10 @@
1
1
  import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
2
2
  import { c as childrenCsr } from "./children-CL3Cy0ez.js";
3
- import { V as resolveExportOptions, X as pairFolding, ax as canonicalId, af as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, a as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, I as ID_MERGED_CODE, O as OPTION_IGNORED_CODE, C as COLUMN_RENAMED_CODE, R as ROLE_TAKEN_CODE, M as MULTIPLE_GRAPHS_CODE, q as UNKNOWN_ENCODING_CODE, E as ENCODING_FALLBACK_CODE, r as INVALID_ENCODING_CODE, s as INVALID_UTF8_CODE, u as EMPTY_INPUT_CODE, t as SYNTAX_CODE, v as resolveImportOptions, w as ImportReportBuilder, z as reportUnusedOptions, aG as readText, F as reportSinkOptions, y as throwIfAborted, K as IdCoercer, J as DirectionResolver, L as declareResolved } from "./report-B1z4WT9e.js";
4
- import { c as quoteDotId, d as isWritableDotText } from "./escape-B-tkk_Cl.js";
5
- import { L as LOSS, a as checkCapabilities, c as capabilities, d as countMixedEdges, s as sanitizeIds } from "./export-Bh60Dv-n.js";
6
- import { e as explicitWeights, f as formatF32, a as formatF64, b as formatDecimal, d as formatInteger, p as parseWeightText } from "./weights-Dzba96G3.js";
7
- import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, p as parseTextCell, T as TextCellWriter } from "./text-Dr0Ifpag.js";
8
- import { j as joinText, e as encodeChunks } from "./writer-C7flM-Ih.js";
3
+ import { L as LOSS, r as resolveExportOptions, a as checkCapabilities, c as capabilities, bE as countMixedEdges, e as explicitWeights, p as pairFolding, b as plural, aE as sanitizeIds, aa as formatF32, ab as formatF64, a9 as idText, $ as agree, aF as formatDecimal, aG as formatInteger, aH as canonicalId, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, I as ID_MERGED_CODE, O as OPTION_IGNORED_CODE, C as COLUMN_RENAMED_CODE, R as ROLE_TAKEN_CODE, o as DUPLICATE_ATTRIBUTE_CODE, P as PRECISION_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, v as ENCODING_CONFLICT_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, E as EMPTY_INPUT_CODE, ak as SYNTAX_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, an as reportUnusedOptions, bC as readText, ao as reportSinkOptions, am as throwIfAborted, ap as graphChosen, ar as IdCoercer, aq as DirectionResolver, aL as parseWeightText, bF as canonicalEncoding, aJ as survivesF32, a1 as declareResolved } from "./export-CHd4tQE2.js";
4
+ import { c as quoteDotId, d as isWritableDotText } from "./escape-D1HPTUrP.js";
5
+ import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, p as parseTextCell, T as TextCellWriter } from "./text-DzXjAiTl.js";
6
+ import { j as joinText, e as encodeChunks, i as indentUnit } from "./writer-DxjgHwSe.js";
7
+ import { i as importChosenGraph } from "./choose-DrXtu_96.js";
9
8
  const DOT_FORMAT = "dot";
10
9
  const DOT_ORIGIN = Object.freeze({ format: DOT_FORMAT });
11
10
  const CLUSTER_COLUMN = "graphty.cluster";
@@ -18,11 +17,17 @@ const KEY_ATTRIBUTE = "key";
18
17
  const PIN_ATTRIBUTE = "pin";
19
18
  const DOT_META_KEY = "dot";
20
19
  const DOT_LOSS = Object.freeze({
21
- /** An id, name or text with a backslash before a quote or a line break, or at its end, cannot be written as a DOT quoted string; export() throws. */
20
+ /**
21
+ * An id, name or text with a backslash before a quote or a line break, or at its end, cannot be written as a DOT
22
+ * quoted string; the save fails.
23
+ */
22
24
  TRAILING_BACKSLASH: "E_DOT_TRAILING_BACKSLASH",
23
- /** A non-finite f32 / f64 cell has no numeric DOT spelling and reads back as text. */
25
+ /** NaN or an infinity has no DOT number spelling; it is written as text and reads back as text. */
24
26
  NON_FINITE: "W_DOT_NON_FINITE",
25
- /** Text cells that look like numbers or booleans read back as such (DOT attribute values are untyped). */
27
+ /**
28
+ * A text value that reads back as a number or a boolean, because the format does not record that it was text (the
29
+ * text "42" reads back as the number 42).
30
+ */
26
31
  TEXT_INFERRED: LOSS.TEXT_INFERRED,
27
32
  /** A plain column named like an attribute the exporter writes for a role (weight, key, pos) is not written. */
28
33
  ATTRIBUTE_CLASH: "W_DOT_ATTRIBUTE_CLASH",
@@ -32,11 +37,14 @@ const DOT_LOSS = Object.freeze({
32
37
  PARENTS_DROPPED: LOSS.PARENTS,
33
38
  /** A position column that is not a node column of 2 or 3 components is not written. */
34
39
  POSITION_SHAPE: "W_DOT_POSITION_SHAPE",
35
- /** An id whose text reads back as the other type under ids: "canonical" (1.5 as text, "1" as 1). */
40
+ /** An id that reads back as a different type, such as the decimal 1.5 as text or the text "1" as the number 1. */
36
41
  ID_TEXT_TYPE: LOSS.ID_TEXT_TYPE,
37
42
  /** A declared column whose every row is unset is not written (DOT writes cells, never declarations). */
38
43
  EMPTY_COLUMN_DROPPED: LOSS.EMPTY_COLUMN,
39
- /** A role-less column named `label` reads back with the label role. */
44
+ /**
45
+ * An attribute without a role is written where the format keeps a role (for example, a `name` column as the label), and
46
+ * reads back with that role.
47
+ */
40
48
  ROLE_ASSUMED: LOSS.ROLE_ASSUMED,
41
49
  /** A parent that is a plain node is written as a node and a cluster of one name; it reads back marked as a cluster. */
42
50
  CLUSTER_MARKED: "W_DOT_CLUSTER_MARKED"
@@ -70,7 +78,7 @@ const CAPABILITIES = capabilities({
70
78
  });
71
79
  const DEFAULT_INDENT = " ";
72
80
  const CLUSTER_PREFIX$1 = "cluster";
73
- const COMPASS_POINTS = /* @__PURE__ */ new Set(["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "_"]);
81
+ const COMPASS_POINTS$1 = /* @__PURE__ */ new Set(["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "_"]);
74
82
  const SKIPPED_NODE_ROLES = /* @__PURE__ */ new Set([
75
83
  "parent",
76
84
  "parents",
@@ -120,6 +128,7 @@ const SKIPPED_GRAPH_ROLES = /* @__PURE__ */ new Set(["position", "color", "size"
120
128
  const TEXT_ROLES = /* @__PURE__ */ new Set(["label", "id", "sourcePort", "targetPort"]);
121
129
  const dotExporter = Object.freeze({
122
130
  format: DOT_FORMAT,
131
+ options: Object.freeze(["indent", "name", "strict"]),
123
132
  capabilities: CAPABILITIES,
124
133
  /**
125
134
  * Pre-flight: every loss the DOT text would incur, without writing anything.
@@ -188,7 +197,7 @@ function writeId(text) {
188
197
  }
189
198
  function writePort(port) {
190
199
  const colon = port.lastIndexOf(":");
191
- if (colon > 0 && COMPASS_POINTS.has(port.slice(colon + 1))) {
200
+ if (colon > 0 && COMPASS_POINTS$1.has(port.slice(colon + 1))) {
192
201
  return `:${quoteDotId(port.slice(0, colon))}:${port.slice(colon + 1)}`;
193
202
  }
194
203
  return `:${quoteDotId(port)}`;
@@ -196,6 +205,16 @@ function writePort(port) {
196
205
  function isTextualDtype(column) {
197
206
  return column.dtype !== "list" && column.dtype !== "json";
198
207
  }
208
+ function badOption(option, found, expected) {
209
+ return new GraphFormatError(
210
+ "E_UNSUPPORTED",
211
+ `option ${option} of the DOT exporter: expected ${expected}, got ${JSON.stringify(found)}`,
212
+ {
213
+ option,
214
+ found
215
+ }
216
+ );
217
+ }
199
218
  class ExportPlan {
200
219
  /**
201
220
  * Plan one export.
@@ -207,9 +226,16 @@ class ExportPlan {
207
226
  this.extraNotes = [];
208
227
  this.snapshot = snapshot;
209
228
  this.resolved = resolved;
210
- this.indent = options?.indent ?? DEFAULT_INDENT;
211
- this.name = options?.name === void 0 ? snapshot.meta.name : options.name;
212
- this.strict = options?.strict ?? isStrictMeta(snapshot);
229
+ const { indent, name, strict } = options ?? {};
230
+ if (name !== void 0 && name !== null && typeof name !== "string") {
231
+ throw badOption("name", name, "a string or null");
232
+ }
233
+ if (strict !== void 0 && typeof strict !== "boolean") {
234
+ throw badOption("strict", strict, "a boolean");
235
+ }
236
+ this.indent = indentUnit(indent, DEFAULT_INDENT);
237
+ this.name = name === void 0 ? snapshot.meta.name : name;
238
+ this.strict = strict ?? isStrictMeta(snapshot);
213
239
  this.mixed = countMixedEdges(snapshot);
214
240
  if (this.mixed > 0 && resolved.onMixedDirection !== "error") {
215
241
  this.directed = resolved.onMixedDirection === "directed";
@@ -308,7 +334,7 @@ class ExportPlan {
308
334
  if (unwritable > 0) {
309
335
  note(
310
336
  DOT_LOSS.TRAILING_BACKSLASH,
311
- `${unwritable} id(s), name(s) or text value(s) hold a backslash before a quote or a line break, or at the end, which a DOT quoted string cannot carry; export() will throw`,
337
+ `${unwritable} ids, names or text values hold a backslash before a quote or a line break, or at the end, which a DOT quoted string cannot carry; the save fails`,
312
338
  null,
313
339
  unwritable
314
340
  );
@@ -341,7 +367,7 @@ class ExportPlan {
341
367
  if (bad > 0) {
342
368
  note(
343
369
  DOT_LOSS.NON_FINITE,
344
- `${label} column "${column.meta.name}" holds ${bad} non-finite value(s) with no numeric DOT spelling; they read back as text`,
370
+ `${label} column "${column.meta.name}" holds ${bad} non-finite value${plural(bad)} with no numeric DOT spelling; they read back as text`,
345
371
  column.meta.name,
346
372
  bad
347
373
  );
@@ -352,7 +378,7 @@ class ExportPlan {
352
378
  if (typed > 0) {
353
379
  note(
354
380
  DOT_LOSS.TEXT_INFERRED,
355
- `${label} column "${column.meta.name}" holds ${typed} text value(s) that look like numbers or booleans; DOT values are untyped and they read back as such`,
381
+ `${label} column "${column.meta.name}" holds ${typed} text value${plural(typed)} that look like numbers or booleans; DOT values are untyped and they read back as such`,
356
382
  column.meta.name,
357
383
  typed
358
384
  );
@@ -370,7 +396,7 @@ class ExportPlan {
370
396
  if (unmarked > 0) {
371
397
  note(
372
398
  DOT_LOSS.CLUSTER_MARKED,
373
- `${unmarked} parent node(s) are written as a node and a cluster of the same name and read back with "${CLUSTER_COLUMN}" true`,
399
+ `${unmarked} parent node${plural(unmarked)} ${agree(unmarked, "is", "are")} written as a node and a cluster of the same name and read back with "${CLUSTER_COLUMN}" true`,
374
400
  CLUSTER_COLUMN,
375
401
  unmarked
376
402
  );
@@ -379,7 +405,7 @@ class ExportPlan {
379
405
  if (mutual > 0) {
380
406
  note(
381
407
  DOT_LOSS.MUTUAL_EXPANDED,
382
- `${mutual} mutual pair(s) are written as two directed edges each; the mutual mark is lost`,
408
+ `${mutual} mutual pair${plural(mutual)} ${agree(mutual, "is", "are")} written as two directed edges each; the mutual mark is lost`,
383
409
  null,
384
410
  mutual
385
411
  );
@@ -419,7 +445,7 @@ class ExportPlan {
419
445
  if (textIds > 0) {
420
446
  note(
421
447
  DOT_LOSS.ID_TEXT_TYPE,
422
- `${textIds} node id(s) read back as the other type under ids: "canonical" (a string "1" becomes 1, a number 1.5 becomes "1.5")`,
448
+ `${textIds} node id${plural(textIds)} ${agree(textIds, "reads", "read")} back as the other type under ids: "canonical" (a string "1" becomes 1, a number 1.5 becomes "1.5")`,
423
449
  null,
424
450
  textIds
425
451
  );
@@ -434,7 +460,7 @@ class ExportPlan {
434
460
  if (this.mixed > 0 && this.resolved.onMixedDirection === "error") {
435
461
  throw new GraphFormatError(
436
462
  "E_DIRECTED",
437
- `${this.mixed} undirected edge(s) in a directed graph; DOT has no mixed direction and onMixedDirection is "error"`,
463
+ `${this.mixed} undirected edge${plural(this.mixed)} in a directed graph, and DOT holds one direction per file, so the save fails unless onMixedDirection is "directed" or "undirected"`,
438
464
  { reason: LOSS.MIXED_DIRECTION_ERROR, count: this.mixed }
439
465
  );
440
466
  }
@@ -549,22 +575,22 @@ class ExportPlan {
549
575
  }
550
576
  emitted[i] = 1;
551
577
  const pad = this.indent.repeat(depth);
552
- const idText = this.idText(i);
578
+ const idText2 = this.idText(i);
553
579
  const kids = this.children.childrenOf(i);
554
580
  const marked = this.cluster !== null && this.cluster.isSet(i) && this.cluster.value(i) === true;
555
581
  if (kids.length === 0 && !marked) {
556
- yield `${pad}${this.nodeStatement(i, idText)};
582
+ yield `${pad}${this.nodeStatement(i, idText2)};
557
583
  `;
558
584
  return;
559
585
  }
560
586
  if (!marked) {
561
- yield `${pad}${this.nodeStatement(i, idText)};
587
+ yield `${pad}${this.nodeStatement(i, idText2)};
562
588
  `;
563
589
  }
564
590
  const inner = `${pad}${this.indent}`;
565
- yield `${pad}subgraph ${writeId(idText)} {
591
+ yield `${pad}subgraph ${writeId(idText2)} {
566
592
  `;
567
- if (!idText.startsWith(CLUSTER_PREFIX$1)) {
593
+ if (!idText2.startsWith(CLUSTER_PREFIX$1)) {
568
594
  yield `${inner}cluster=true;
569
595
  `;
570
596
  }
@@ -592,9 +618,9 @@ class ExportPlan {
592
618
  * @param idText - the id text
593
619
  * @returns `id` or `id [attrs]`
594
620
  */
595
- nodeStatement(i, idText) {
621
+ nodeStatement(i, idText2) {
596
622
  const attributes = this.nodeAttributes(i);
597
- return attributes.length === 0 ? writeId(idText) : `${writeId(idText)} [${attributes.join(", ")}]`;
623
+ return attributes.length === 0 ? writeId(idText2) : `${writeId(idText2)} [${attributes.join(", ")}]`;
598
624
  }
599
625
  /**
600
626
  * The attributes of a node: its set cells plus `pos` from the position column.
@@ -717,12 +743,9 @@ class ExportPlan {
717
743
  * @returns String(id)
718
744
  */
719
745
  idText(i) {
720
- return idToText(this.snapshot.ids.idOf(i));
746
+ return idText(this.snapshot.ids.idOf(i));
721
747
  }
722
748
  }
723
- function idToText(id) {
724
- return typeof id === "string" ? id : formatF64(id);
725
- }
726
749
  function isStrictMeta(snapshot) {
727
750
  const dot = snapshot.meta.extra[DOT_META_KEY];
728
751
  return typeof dot === "object" && dot !== null && dot.strict === true;
@@ -811,7 +834,7 @@ function countTextIds(snapshot) {
811
834
  let count = 0;
812
835
  for (let i = 0; i < ids.size; i++) {
813
836
  const id = ids.idOf(i);
814
- if (canonicalId(idToText(id)) !== id) {
837
+ if (canonicalId(idText(id)) !== id) {
815
838
  count++;
816
839
  }
817
840
  }
@@ -831,10 +854,11 @@ class DotSyntaxError extends Error {
831
854
  }
832
855
  const EOF_TOKEN_TEXT = "";
833
856
  function isIdentifierStart(c) {
834
- return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95 || c >= 128;
857
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95 || c >= 128 && c !== BOM_CODE;
835
858
  }
859
+ const BOM_CODE = 65279;
836
860
  function isIdentifierPart(c) {
837
- return isIdentifierStart(c) || isDigit(c);
861
+ return isIdentifierStart(c) || isDigit(c) || c === BOM_CODE;
838
862
  }
839
863
  function isDigit(c) {
840
864
  return c >= 48 && c <= 57;
@@ -957,7 +981,8 @@ class DotTokenizer {
957
981
  }
958
982
  this.pos = end;
959
983
  const numeral = text.slice(start, end);
960
- if (end < text.length && isIdentifierStart(text.charCodeAt(end)) && this.onAmbiguity !== null) {
984
+ const after = text.charCodeAt(end);
985
+ if (end < text.length && (isIdentifierStart(after) || after === 46) && this.onAmbiguity !== null) {
961
986
  this.onAmbiguity(numeral, line);
962
987
  }
963
988
  return { kind: "id", text: numeral, quoted: false, html: false, line };
@@ -1068,6 +1093,10 @@ class DotTokenizer {
1068
1093
  this.pos++;
1069
1094
  continue;
1070
1095
  }
1096
+ if (c === BOM_CODE) {
1097
+ this.pos++;
1098
+ continue;
1099
+ }
1071
1100
  if (c === 47) {
1072
1101
  const d = text.charCodeAt(this.pos + 1);
1073
1102
  if (d === 47) {
@@ -1128,24 +1157,41 @@ class DotTokenizer {
1128
1157
  }
1129
1158
  }
1130
1159
  const DOT_ISSUE = Object.freeze({
1131
- /** A grammar violation; fatal. */
1160
+ ...INPUT_ISSUE,
1161
+ ...ELEMENT_ISSUE,
1162
+ /** The text breaks DOT's syntax; the message says where. The import stops. */
1132
1163
  SYNTAX: SYNTAX_CODE,
1133
- /** The input holds no graph at all (empty or only comments); fatal. */
1164
+ /** The input holds no graph: it is empty or only comments. The import stops. */
1134
1165
  EMPTY_INPUT: EMPTY_INPUT_CODE,
1135
- /** The input holds invalid UTF-8 (fatal). */
1166
+ /** The input is not valid UTF-8. The import stops. */
1136
1167
  INVALID_UTF8: INVALID_UTF8_CODE,
1137
- /** Invalid bytes in the encoding a BOM, a declaration or the encoding option chose (fatal). */
1168
+ /**
1169
+ * Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
1170
+ * `encoding` option). The import stops.
1171
+ */
1138
1172
  INVALID_ENCODING: INVALID_ENCODING_CODE,
1139
1173
  /** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
1140
1174
  ENCODING_FALLBACK: ENCODING_FALLBACK_CODE,
1141
1175
  /** A declared encoding the platform cannot decode was ignored. */
1142
1176
  UNKNOWN_ENCODING: UNKNOWN_ENCODING_CODE,
1143
- /** Subgraphs or braces nested deeper than the parser's limit; fatal. */
1177
+ /** A declared encoding the byte order mark contradicts (the mark wins). */
1178
+ ENCODING_CONFLICT: ENCODING_CONFLICT_CODE,
1179
+ /** Subgraphs or braces are nested deeper than graph-io reads. The import stops. */
1144
1180
  NESTING: "E_DOT_NESTING",
1145
- /** An edge operator contradicting the graph keyword (warning under "operator" / "header"). */
1181
+ /**
1182
+ * An edge operator contradicting the graph keyword, read under mismatchedEdgeOperator "operator" or "header".
1183
+ * Under "error" the import stops with E_SYNTAX instead.
1184
+ */
1146
1185
  EDGE_OPERATOR: "W_DOT_EDGE_OPERATOR",
1147
- /** A second graph in the same input; only the first is read. */
1186
+ /**
1187
+ * The file holds several graphs and only the first was read. It is not added when `graphIndex` or `graphName` chose the graph.
1188
+ * `importAllGraphs()` reads every one.
1189
+ */
1148
1190
  MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
1191
+ /** `graphIndex` or `graphName` names no graph of the file; the message lists the graphs it holds. The import stops. */
1192
+ GRAPH_NOT_FOUND: GRAPH_NOT_FOUND_CODE,
1193
+ /** `graphName` matches more than one graph; pass `graphIndex`. The import stops. */
1194
+ AMBIGUOUS_GRAPH_NAME: AMBIGUOUS_GRAPH_NAME_CODE,
1149
1195
  /** A badly delimited numeral (`1e3`) split into two tokens, as Graphviz does with a warning. */
1150
1196
  NUMERAL_AMBIGUITY: "W_DOT_NUMERAL_AMBIGUITY",
1151
1197
  /** Attributes of a subgraph that is not a cluster (rank=same and the like) cannot be represented. */
@@ -1156,29 +1202,58 @@ const DOT_ISSUE = Object.freeze({
1156
1202
  CLUSTER_NODE_MERGED: "W_DOT_CLUSTER_NODE_MERGED",
1157
1203
  /** A node mentioned in two unrelated clusters keeps the first. */
1158
1204
  CLUSTER_CONFLICT: "W_DOT_CLUSTER_CONFLICT",
1159
- /** A node `pos` that is not a point; the value was dropped. */
1205
+ /** A node's `pos` is not a point, or is too large for a 32-bit float position; the value was dropped. */
1160
1206
  BAD_POS: "W_DOT_BAD_POS",
1207
+ /** Node `pos` values mix two and three coordinates; the position column records the first's. */
1208
+ POS_DIMS: "W_DOT_POS_DIMS",
1209
+ /** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
1210
+ PRECISION: PRECISION_CODE,
1211
+ /** The same attribute twice in one statement's attribute lists; the last value stands, as in Graphviz. */
1212
+ DUPLICATE_ATTRIBUTE: DUPLICATE_ATTRIBUTE_CODE,
1213
+ /** The second part of a port (`a:p:zz`) is not a compass point; kept as written, as Graphviz warns. */
1214
+ COMPASS_POINT: "W_DOT_COMPASS_POINT",
1215
+ /** A `charset` attribute beyond the head the decoder reads it from; the input was decoded without it. */
1216
+ LATE_CHARSET: "W_DOT_LATE_CHARSET",
1161
1217
  /** A parallel edge merged into an earlier one under `strict`. */
1162
1218
  STRICT_MERGED: "W_DOT_STRICT_MERGED",
1163
1219
  /** An edge merged into an earlier one with the same endpoints and `key`. */
1164
1220
  KEY_MERGED: "W_DOT_KEY_MERGED",
1165
- /** A role (label, id, position, ...) was already taken in the caller's sink; the column was declared without it. */
1221
+ /**
1222
+ * You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
1223
+ * a plain attribute.
1224
+ */
1166
1225
  ROLE_TAKEN: ROLE_TAKEN_CODE,
1167
- /** A column of another shape exists in the caller's sink under a name the importer declares; renamed `<name>#<id>`. */
1226
+ /**
1227
+ * An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example
1228
+ * two attributes declared with the same name.
1229
+ */
1168
1230
  COLUMN_RENAMED: COLUMN_RENAMED_CODE,
1169
- /** A common option the format has no use for was given a non-default value. */
1231
+ /** You set an option this format does not use; it had no effect. The message names the option. */
1170
1232
  OPTION_IGNORED: OPTION_IGNORED_CODE,
1171
- /** Two distinct id texts merged under ids: "number". */
1233
+ /** Two different id texts became the same number because `ids` is "number", so their nodes were merged. */
1172
1234
  ID_MERGED: ID_MERGED_CODE,
1173
- /** A builder-policy option the sink does not honour. */
1235
+ /**
1236
+ * You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
1237
+ * `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
1238
+ */
1174
1239
  SINK_OPTION: SINK_OPTION_CODE,
1175
- /** The sink refused the file's direction. */
1240
+ /**
1241
+ * You read into a graph builder whose direction is already set, or which already holds edges, so the file is read
1242
+ * with the builder's direction instead of its own.
1243
+ */
1176
1244
  DIRECTION_REFUSED: DIRECTION_REFUSED_CODE,
1177
- /** Edges forced to the policy's direction. */
1245
+ /** Edges of the other direction were read with the direction `onMixedDirection` chose. */
1178
1246
  DIRECTION_FORCED: DIRECTION_FORCED_CODE,
1179
- /** A mixed file under onMixedDirection "error" (fatal). */
1247
+ /**
1248
+ * The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
1249
+ * format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
1250
+ * it anyway.
1251
+ */
1180
1252
  MIXED_DIRECTION: MIXED_DIRECTION_CODE,
1181
- /** A text column the sink could not widen to the dtype its cells imply. */
1253
+ /**
1254
+ * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of
1255
+ * its first values.
1256
+ */
1182
1257
  WIDENING_UNSUPPORTED: WIDENING_UNSUPPORTED_CODE
1183
1258
  });
1184
1259
  const USED_OPTIONS = /* @__PURE__ */ new Set([
@@ -1202,9 +1277,14 @@ const STATEMENTS_PER_ABORT_CHECK = 64;
1202
1277
  const MAX_ANCESTOR_WALK = 4096;
1203
1278
  const DOT_HEADER = /^\s*(strict\s+)?(di)?graph(?=[\s{"/]|$)(?!\s*\[)/i;
1204
1279
  const TRUE_TEXTS = /* @__PURE__ */ new Set(["true", "yes", "1"]);
1205
- 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*$/;
1280
+ const COMPASS_POINTS = /* @__PURE__ */ new Set(["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "_"]);
1281
+ const POINT_NUMBER = String.raw`[-+]?(?:\d+(?:\.\d+)?|\.\d+)(?:[eE][-+]?\d+)?`;
1282
+ const POINT_TEXT = new RegExp(
1283
+ String.raw`^\s*(${POINT_NUMBER})\s*,\s*(${POINT_NUMBER})(?:\s*,\s*(${POINT_NUMBER}))?\s*(?:(!)\s*)?$`
1284
+ );
1206
1285
  const dotImporter = Object.freeze({
1207
1286
  format: DOT_FORMAT,
1287
+ options: Object.freeze(["mismatchedEdgeOperator", "positions"]),
1208
1288
  extensions: EXTENSIONS,
1209
1289
  mimeTypes: MIME_TYPES,
1210
1290
  /**
@@ -1229,6 +1309,9 @@ const dotImporter = Object.freeze({
1229
1309
  * @returns the import report; ImportError (E_IMPORT) on a syntax error or beyond the error limit
1230
1310
  */
1231
1311
  async import(input, sink, options) {
1312
+ if (graphChosen(options)) {
1313
+ return importChosenGraph(dotImporter, input, sink, options);
1314
+ }
1232
1315
  const resolved = resolveImportOptions(options, {
1233
1316
  ids: "canonical",
1234
1317
  defaultDirected: true,
@@ -1238,21 +1321,24 @@ const dotImporter = Object.freeze({
1238
1321
  const report = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
1239
1322
  reportUnusedOptions(options, report, USED_OPTIONS);
1240
1323
  reportSinkOptions(sink, options, report);
1241
- const text = await readText(input, report, { ...resolved, declaredEncoding: dotCharset });
1324
+ const head = {};
1325
+ const text = await readText(input, report, {
1326
+ ...resolved,
1327
+ declaredEncoding: (h) => head.charset = dotCharset(h),
1328
+ declarationBytes: CHARSET_HEAD_BYTES
1329
+ });
1242
1330
  const reports = { current: report };
1243
1331
  const lexer = dotLexer(text, reports);
1244
1332
  const first = guard(report, () => lexer.next());
1245
- const trailing = parseGraph(
1246
- new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false),
1247
- report,
1248
- first
1249
- );
1333
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
1334
+ parser.headCharset = head.charset;
1335
+ const trailing = parseGraph(parser, report, first);
1250
1336
  if (trailing.kind !== "eof") {
1251
1337
  const skipped = guard(report, () => countGraphs(lexer, trailing));
1252
1338
  report.warning(
1253
1339
  "unsupported",
1254
1340
  MULTIPLE_GRAPHS_CODE,
1255
- `the input holds ${skipped} more graph(s) after the first; import() reads the first, importAll() reads every one`,
1341
+ `the input holds ${skipped} more graph${plural(skipped)} after the first; the first is read (graphIndex or graphName chooses another; importAllGraphs() reads every one)`,
1256
1342
  { line: trailing.line }
1257
1343
  );
1258
1344
  }
@@ -1275,7 +1361,12 @@ const dotImporter = Object.freeze({
1275
1361
  const mismatch = mismatchOption(options?.mismatchedEdgeOperator);
1276
1362
  const first = new ImportReportBuilder(DOT_FORMAT, resolved.errorLimit);
1277
1363
  reportUnusedOptions(options, first, USED_OPTIONS);
1278
- const text = await readText(input, first, { ...resolved, declaredEncoding: dotCharset });
1364
+ const head = {};
1365
+ const text = await readText(input, first, {
1366
+ ...resolved,
1367
+ declaredEncoding: (h) => head.charset = dotCharset(h),
1368
+ declarationBytes: CHARSET_HEAD_BYTES
1369
+ });
1279
1370
  const reports = { current: first };
1280
1371
  const lexer = dotLexer(text, reports);
1281
1372
  const done = [];
@@ -1285,11 +1376,9 @@ const dotImporter = Object.freeze({
1285
1376
  reports.current = report;
1286
1377
  const sink = sinkFor(done.length);
1287
1378
  reportSinkOptions(sink, options, report);
1288
- token = parseGraph(
1289
- new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false),
1290
- report,
1291
- token
1292
- );
1379
+ const parser = new DotParser(lexer, sink, report, resolved, mismatch, options?.positions !== false);
1380
+ parser.headCharset = head.charset;
1381
+ token = parseGraph(parser, report, token);
1293
1382
  throwIfAborted(resolved.signal);
1294
1383
  done.push(report.finish());
1295
1384
  } while (token.kind !== "eof");
@@ -1326,6 +1415,9 @@ function countGraphs(lexer, first) {
1326
1415
  if (isKeyword(token, "strict")) {
1327
1416
  token = lexer.next();
1328
1417
  }
1418
+ if (isPunct(token, "}")) {
1419
+ throw new DotSyntaxError('unexpected "}" after the end of the graph: no "{" is open', token.line);
1420
+ }
1329
1421
  if (!isKeyword(token, "graph") && !isKeyword(token, "digraph")) {
1330
1422
  throw new DotSyntaxError(`expected "graph" or "digraph", found ${describeToken(token)}`, token.line);
1331
1423
  }
@@ -1352,10 +1444,35 @@ function countGraphs(lexer, first) {
1352
1444
  }
1353
1445
  return count;
1354
1446
  }
1355
- const DOT_CHARSET = /\bcharset\s*=\s*"?([A-Za-z][A-Za-z0-9._-]*)/i;
1447
+ const CHARSET_HEAD_BYTES = 64 * 1024;
1356
1448
  function dotCharset(head) {
1357
- const match = DOT_CHARSET.exec(head);
1358
- return match === null ? null : match[1].replace(/^(latin|big)-/i, "$1");
1449
+ const lexer = new DotTokenizer(head);
1450
+ let list = null;
1451
+ let previous = null;
1452
+ try {
1453
+ let token = lexer.next();
1454
+ while (token.kind !== "eof") {
1455
+ if (isPunct(token, "[")) {
1456
+ list = previous !== null && isKeyword(previous, "graph") ? "graph" : "other";
1457
+ } else if (isPunct(token, "]")) {
1458
+ list = null;
1459
+ } else if (list !== "other" && isKeyword(token, "charset")) {
1460
+ const equals = lexer.next();
1461
+ const value = isPunct(equals, "=") ? lexer.next() : equals;
1462
+ if (value !== equals && value.kind === "id") {
1463
+ return value.text.replace(/^(latin|big)-/i, "$1");
1464
+ }
1465
+ token = value;
1466
+ }
1467
+ previous = token;
1468
+ token = lexer.next();
1469
+ }
1470
+ } catch (err) {
1471
+ if (!(err instanceof DotSyntaxError)) {
1472
+ throw err;
1473
+ }
1474
+ }
1475
+ return null;
1359
1476
  }
1360
1477
  function mismatchOption(value) {
1361
1478
  if (value === void 0) {
@@ -1440,6 +1557,8 @@ class DotParser {
1440
1557
  this.sourcePortHandle = INVALID_INDEX;
1441
1558
  this.targetPortHandle = INVALID_INDEX;
1442
1559
  this.depth = 0;
1560
+ this.posDims = 0;
1561
+ this.headCharset = void 0;
1443
1562
  this.nodeWriters = /* @__PURE__ */ new Map();
1444
1563
  this.edgeWriters = /* @__PURE__ */ new Map();
1445
1564
  this.lexer = lexer;
@@ -1632,7 +1751,16 @@ class DotParser {
1632
1751
  let { text } = this.identifier();
1633
1752
  if (isPunct(lexer.peek(), ":")) {
1634
1753
  lexer.next();
1635
- text += `:${this.identifier().text}`;
1754
+ const compass = this.identifier();
1755
+ text += `:${compass.text}`;
1756
+ if (!COMPASS_POINTS.has(compass.text)) {
1757
+ this.report.warning(
1758
+ "validation-error",
1759
+ DOT_ISSUE.COMPASS_POINT,
1760
+ `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`,
1761
+ { line: compass.line, element: text }
1762
+ );
1763
+ }
1636
1764
  }
1637
1765
  return text;
1638
1766
  }
@@ -1872,6 +2000,7 @@ class DotParser {
1872
2000
  attributeList() {
1873
2001
  const { lexer } = this;
1874
2002
  const out = [];
2003
+ const names = /* @__PURE__ */ new Set();
1875
2004
  while (isPunct(lexer.peek(), "[")) {
1876
2005
  lexer.next();
1877
2006
  for (; ; ) {
@@ -1893,6 +2022,15 @@ class DotParser {
1893
2022
  );
1894
2023
  }
1895
2024
  const value = this.identifier();
2025
+ if (names.has(name.text)) {
2026
+ this.report.warning(
2027
+ "merged",
2028
+ DOT_ISSUE.DUPLICATE_ATTRIBUTE,
2029
+ `attribute ${JSON.stringify(name.text)} is set twice in one statement; the last value ${JSON.stringify(value.text)} stands`,
2030
+ { line: name.line, element: name.text }
2031
+ );
2032
+ }
2033
+ names.add(name.text);
1896
2034
  out.push({ name: name.text, value: value.text, line: name.line });
1897
2035
  }
1898
2036
  }
@@ -1991,7 +2129,7 @@ class DotParser {
1991
2129
  this.report.warnOnce(
1992
2130
  "coercion",
1993
2131
  DOT_ISSUE.EDGE_OPERATOR,
1994
- `${message}; read with the operator's direction and resolved per onMixedDirection`,
2132
+ `${message}; read with the operator's direction, and onMixedDirection decides how the mixed graph is stored`,
1995
2133
  { line: op.line }
1996
2134
  );
1997
2135
  return operatorDirected ? "directed" : "undirected";
@@ -2084,7 +2222,7 @@ class DotParser {
2084
2222
  const weightText = weightFrom === null ? void 0 : effective.get(weightFrom);
2085
2223
  if (weightText !== void 0) {
2086
2224
  try {
2087
- weight = parseWeightText(weightText);
2225
+ weight = parseWeightText(weightText, this.report);
2088
2226
  } catch (err) {
2089
2227
  this.report.recordError(err, where);
2090
2228
  this.report.counts.skippedEdges++;
@@ -2232,6 +2370,17 @@ class DotParser {
2232
2370
  * @param attribute - the attribute
2233
2371
  */
2234
2372
  setGraphAttribute(attribute) {
2373
+ if (attribute.name.toLowerCase() === "charset" && this.headCharset === null) {
2374
+ const canonical = canonicalEncoding(attribute.value);
2375
+ if (canonical !== "utf-8") {
2376
+ this.report.warning(
2377
+ "unsupported",
2378
+ DOT_ISSUE.LATE_CHARSET,
2379
+ `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`,
2380
+ { line: attribute.line, element: attribute.name }
2381
+ );
2382
+ }
2383
+ }
2235
2384
  try {
2236
2385
  if (attribute.name === LABEL_ATTRIBUTE) {
2237
2386
  this.sink.setGraphValue(attribute.name, attribute.value, { dtype: "string", origin: DOT_ORIGIN });
@@ -2267,7 +2416,36 @@ class DotParser {
2267
2416
  const y = Number(match[2]);
2268
2417
  const z = match[3] === void 0 ? 0 : Number(match[3]);
2269
2418
  const dims = match[3] === void 0 ? 2 : 3;
2270
- this.sink.setNodeValue(this.positionColumn(dims), index, [x, y, z]);
2419
+ const point = [x, y, z];
2420
+ if (point.some((v) => !Number.isFinite(Math.fround(v)))) {
2421
+ this.report.warning(
2422
+ "validation-error",
2423
+ DOT_ISSUE.BAD_POS,
2424
+ `pos ${JSON.stringify(text)} is beyond the f32 range of the position column; dropped`,
2425
+ { line, element }
2426
+ );
2427
+ return;
2428
+ }
2429
+ if (!point.every(survivesF32)) {
2430
+ this.report.warnOnce(
2431
+ "precision",
2432
+ DOT_ISSUE.PRECISION,
2433
+ `pos ${JSON.stringify(text)} has a coordinate the f32 position column rounds (warned once; positions=false keeps pos as written)`,
2434
+ { line, element },
2435
+ `${DOT_ISSUE.PRECISION}:pos`
2436
+ );
2437
+ }
2438
+ if (this.posDims === 0) {
2439
+ this.posDims = dims;
2440
+ } else if (dims !== this.posDims) {
2441
+ this.report.warnOnce(
2442
+ "validation-error",
2443
+ DOT_ISSUE.POS_DIMS,
2444
+ `pos values mix ${this.posDims} and ${dims} coordinates; the position column records sourceDims ${this.posDims}`,
2445
+ { line, element }
2446
+ );
2447
+ }
2448
+ this.sink.setNodeValue(this.positionColumn(dims), index, point);
2271
2449
  if (match[4] === "!") {
2272
2450
  this.sink.setNodeValue(PIN_ATTRIBUTE, index, true);
2273
2451
  }
@@ -2464,4 +2642,4 @@ export {
2464
2642
  dotImporter as b,
2465
2643
  dotExporter as d
2466
2644
  };
2467
- //# sourceMappingURL=importer-BWY2FFc5.js.map
2645
+ //# sourceMappingURL=importer-B1wmPQjr.js.map