@graphty/graph-io 0.3.25 → 0.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (581) hide show
  1. package/README.md +49 -414
  2. package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
  3. package/dist/chunks/choose-BbJI55dx.js +56 -0
  4. package/dist/chunks/choose-BbJI55dx.js.map +1 -0
  5. package/dist/chunks/constants-BCsFsMj4.js +231 -0
  6. package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
  7. package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
  8. package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
  9. package/dist/chunks/export-BTI4yQgy.js +4333 -0
  10. package/dist/chunks/export-BTI4yQgy.js.map +1 -0
  11. package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
  12. package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
  13. package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
  14. package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
  15. package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
  16. package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
  17. package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
  18. package/dist/chunks/exporter-tne475KK.js.map +1 -0
  19. package/dist/chunks/importer-90YWhJoF.js +2811 -0
  20. package/dist/chunks/importer-90YWhJoF.js.map +1 -0
  21. package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
  22. package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
  23. package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
  24. package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
  25. package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
  26. package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
  27. package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
  28. package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
  29. package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
  30. package/dist/chunks/importer-DfVu6j59.js.map +1 -0
  31. package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
  32. package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
  33. package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
  34. package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
  35. package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
  36. package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
  37. package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
  38. package/dist/chunks/records-CQXT__mY.js.map +1 -0
  39. package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
  40. package/dist/chunks/text-DmcUs5_Q.js.map +1 -0
  41. package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
  42. package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
  43. package/dist/csv.js +951 -261
  44. package/dist/csv.js.map +1 -1
  45. package/dist/cx.js +6 -3
  46. package/dist/cx2.js +2 -2
  47. package/dist/cys.js +6 -3
  48. package/dist/dot.js +1 -1
  49. package/dist/gexf.js +554 -122
  50. package/dist/gexf.js.map +1 -1
  51. package/dist/gml.js +342 -85
  52. package/dist/gml.js.map +1 -1
  53. package/dist/graph-io.js +1105 -213
  54. package/dist/graph-io.js.map +1 -1
  55. package/dist/graphml.js +3 -2
  56. package/dist/graphml.js.map +1 -1
  57. package/dist/json.js +3 -2
  58. package/dist/neo4j.js +564 -157
  59. package/dist/neo4j.js.map +1 -1
  60. package/dist/obo.js +6 -3
  61. package/dist/pajek.js +1 -1
  62. package/dist/src/children.d.ts +18 -6
  63. package/dist/src/children.d.ts.map +1 -1
  64. package/dist/src/children.js +6 -3
  65. package/dist/src/children.js.map +1 -1
  66. package/dist/src/common/attributes.d.ts +29 -11
  67. package/dist/src/common/attributes.d.ts.map +1 -1
  68. package/dist/src/common/attributes.js +25 -7
  69. package/dist/src/common/attributes.js.map +1 -1
  70. package/dist/src/common/cell-budget.d.ts +9 -2
  71. package/dist/src/common/cell-budget.d.ts.map +1 -1
  72. package/dist/src/common/cell-budget.js +11 -3
  73. package/dist/src/common/cell-budget.js.map +1 -1
  74. package/dist/src/common/choose.d.ts +19 -0
  75. package/dist/src/common/choose.d.ts.map +1 -0
  76. package/dist/src/common/choose.js +72 -0
  77. package/dist/src/common/choose.js.map +1 -0
  78. package/dist/src/common/codes.d.ts +456 -66
  79. package/dist/src/common/codes.d.ts.map +1 -1
  80. package/dist/src/common/codes.js +458 -66
  81. package/dist/src/common/codes.js.map +1 -1
  82. package/dist/src/common/compare.d.ts +81 -0
  83. package/dist/src/common/compare.d.ts.map +1 -0
  84. package/dist/src/common/compare.js +394 -0
  85. package/dist/src/common/compare.js.map +1 -0
  86. package/dist/src/common/cx-export.d.ts +123 -0
  87. package/dist/src/common/cx-export.d.ts.map +1 -0
  88. package/dist/src/common/cx-export.js +334 -0
  89. package/dist/src/common/cx-export.js.map +1 -0
  90. package/dist/src/common/declared-types.d.ts +22 -2
  91. package/dist/src/common/declared-types.d.ts.map +1 -1
  92. package/dist/src/common/declared-types.js +19 -1
  93. package/dist/src/common/declared-types.js.map +1 -1
  94. package/dist/src/common/direction.d.ts +74 -50
  95. package/dist/src/common/direction.d.ts.map +1 -1
  96. package/dist/src/common/direction.js +47 -27
  97. package/dist/src/common/direction.js.map +1 -1
  98. package/dist/src/common/escape.d.ts +21 -9
  99. package/dist/src/common/escape.d.ts.map +1 -1
  100. package/dist/src/common/escape.js +33 -17
  101. package/dist/src/common/escape.js.map +1 -1
  102. package/dist/src/common/export.d.ts +144 -32
  103. package/dist/src/common/export.d.ts.map +1 -1
  104. package/dist/src/common/export.js +216 -42
  105. package/dist/src/common/export.js.map +1 -1
  106. package/dist/src/common/format.d.ts +23 -1
  107. package/dist/src/common/format.d.ts.map +1 -1
  108. package/dist/src/common/format.js +26 -1
  109. package/dist/src/common/format.js.map +1 -1
  110. package/dist/src/common/ids.d.ts +9 -2
  111. package/dist/src/common/ids.d.ts.map +1 -1
  112. package/dist/src/common/ids.js +6 -2
  113. package/dist/src/common/ids.js.map +1 -1
  114. package/dist/src/common/input.d.ts +122 -28
  115. package/dist/src/common/input.d.ts.map +1 -1
  116. package/dist/src/common/input.js +890 -124
  117. package/dist/src/common/input.js.map +1 -1
  118. package/dist/src/common/json-elements.d.ts +144 -20
  119. package/dist/src/common/json-elements.d.ts.map +1 -1
  120. package/dist/src/common/json-elements.js +868 -188
  121. package/dist/src/common/json-elements.js.map +1 -1
  122. package/dist/src/common/line-format.d.ts +90 -0
  123. package/dist/src/common/line-format.d.ts.map +1 -0
  124. package/dist/src/common/line-format.js +185 -0
  125. package/dist/src/common/line-format.js.map +1 -0
  126. package/dist/src/common/lists.d.ts +6 -1
  127. package/dist/src/common/lists.d.ts.map +1 -1
  128. package/dist/src/common/lists.js +2 -0
  129. package/dist/src/common/lists.js.map +1 -1
  130. package/dist/src/common/ontology-export.d.ts +167 -0
  131. package/dist/src/common/ontology-export.d.ts.map +1 -0
  132. package/dist/src/common/ontology-export.js +359 -0
  133. package/dist/src/common/ontology-export.js.map +1 -0
  134. package/dist/src/common/ontology.d.ts +25 -3
  135. package/dist/src/common/ontology.d.ts.map +1 -1
  136. package/dist/src/common/ontology.js +30 -9
  137. package/dist/src/common/ontology.js.map +1 -1
  138. package/dist/src/common/options.d.ts +62 -12
  139. package/dist/src/common/options.d.ts.map +1 -1
  140. package/dist/src/common/options.js +89 -11
  141. package/dist/src/common/options.js.map +1 -1
  142. package/dist/src/common/plural.d.ts +31 -0
  143. package/dist/src/common/plural.d.ts.map +1 -0
  144. package/dist/src/common/plural.js +46 -0
  145. package/dist/src/common/plural.js.map +1 -0
  146. package/dist/src/common/report.d.ts +72 -14
  147. package/dist/src/common/report.d.ts.map +1 -1
  148. package/dist/src/common/report.js +146 -22
  149. package/dist/src/common/report.js.map +1 -1
  150. package/dist/src/common/temporal.d.ts +22 -5
  151. package/dist/src/common/temporal.d.ts.map +1 -1
  152. package/dist/src/common/temporal.js +13 -2
  153. package/dist/src/common/temporal.js.map +1 -1
  154. package/dist/src/common/text.d.ts +39 -23
  155. package/dist/src/common/text.d.ts.map +1 -1
  156. package/dist/src/common/text.js +51 -21
  157. package/dist/src/common/text.js.map +1 -1
  158. package/dist/src/common/weights.d.ts +37 -4
  159. package/dist/src/common/weights.d.ts.map +1 -1
  160. package/dist/src/common/weights.js +61 -2
  161. package/dist/src/common/weights.js.map +1 -1
  162. package/dist/src/common/writer.d.ts +19 -3
  163. package/dist/src/common/writer.d.ts.map +1 -1
  164. package/dist/src/common/writer.js +30 -2
  165. package/dist/src/common/writer.js.map +1 -1
  166. package/dist/src/common/xml.d.ts +125 -9
  167. package/dist/src/common/xml.d.ts.map +1 -1
  168. package/dist/src/common/xml.js +400 -83
  169. package/dist/src/common/xml.js.map +1 -1
  170. package/dist/src/common/zip.d.ts +44 -4
  171. package/dist/src/common/zip.d.ts.map +1 -1
  172. package/dist/src/common/zip.js +134 -5
  173. package/dist/src/common/zip.js.map +1 -1
  174. package/dist/src/formats/csv/exporter.d.ts +80 -24
  175. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  176. package/dist/src/formats/csv/exporter.js +145 -32
  177. package/dist/src/formats/csv/exporter.js.map +1 -1
  178. package/dist/src/formats/csv/header.d.ts +38 -9
  179. package/dist/src/formats/csv/header.d.ts.map +1 -1
  180. package/dist/src/formats/csv/header.js +46 -10
  181. package/dist/src/formats/csv/header.js.map +1 -1
  182. package/dist/src/formats/csv/importer.d.ts +187 -37
  183. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  184. package/dist/src/formats/csv/importer.js +835 -204
  185. package/dist/src/formats/csv/importer.js.map +1 -1
  186. package/dist/src/formats/csv/index.d.ts +100 -19
  187. package/dist/src/formats/csv/index.d.ts.map +1 -1
  188. package/dist/src/formats/csv/index.js +94 -21
  189. package/dist/src/formats/csv/index.js.map +1 -1
  190. package/dist/src/formats/csv/records.d.ts +95 -10
  191. package/dist/src/formats/csv/records.d.ts.map +1 -1
  192. package/dist/src/formats/csv/records.js +333 -122
  193. package/dist/src/formats/csv/records.js.map +1 -1
  194. package/dist/src/formats/csv/values.d.ts +1 -0
  195. package/dist/src/formats/csv/values.d.ts.map +1 -1
  196. package/dist/src/formats/csv/values.js +1 -0
  197. package/dist/src/formats/csv/values.js.map +1 -1
  198. package/dist/src/formats/cx/exporter.d.ts +102 -0
  199. package/dist/src/formats/cx/exporter.d.ts.map +1 -0
  200. package/dist/src/formats/cx/exporter.js +1217 -0
  201. package/dist/src/formats/cx/exporter.js.map +1 -0
  202. package/dist/src/formats/cx/importer.d.ts +79 -32
  203. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  204. package/dist/src/formats/cx/importer.js +680 -285
  205. package/dist/src/formats/cx/importer.js.map +1 -1
  206. package/dist/src/formats/cx/index.d.ts +4 -3
  207. package/dist/src/formats/cx/index.d.ts.map +1 -1
  208. package/dist/src/formats/cx/index.js +4 -3
  209. package/dist/src/formats/cx/index.js.map +1 -1
  210. package/dist/src/formats/cx2/exporter.d.ts +29 -11
  211. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  212. package/dist/src/formats/cx2/exporter.js +39 -268
  213. package/dist/src/formats/cx2/exporter.js.map +1 -1
  214. package/dist/src/formats/cx2/importer.d.ts +78 -28
  215. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  216. package/dist/src/formats/cx2/importer.js +226 -79
  217. package/dist/src/formats/cx2/importer.js.map +1 -1
  218. package/dist/src/formats/cx2/index.d.ts +2 -1
  219. package/dist/src/formats/cx2/index.d.ts.map +1 -1
  220. package/dist/src/formats/cx2/index.js +2 -1
  221. package/dist/src/formats/cx2/index.js.map +1 -1
  222. package/dist/src/formats/cys/constants.d.ts +66 -17
  223. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  224. package/dist/src/formats/cys/constants.js +59 -18
  225. package/dist/src/formats/cys/constants.js.map +1 -1
  226. package/dist/src/formats/cys/exporter.d.ts +118 -0
  227. package/dist/src/formats/cys/exporter.d.ts.map +1 -0
  228. package/dist/src/formats/cys/exporter.js +1072 -0
  229. package/dist/src/formats/cys/exporter.js.map +1 -0
  230. package/dist/src/formats/cys/importer.d.ts +22 -8
  231. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  232. package/dist/src/formats/cys/importer.js +510 -149
  233. package/dist/src/formats/cys/importer.js.map +1 -1
  234. package/dist/src/formats/cys/index.d.ts +4 -2
  235. package/dist/src/formats/cys/index.d.ts.map +1 -1
  236. package/dist/src/formats/cys/index.js +4 -2
  237. package/dist/src/formats/cys/index.js.map +1 -1
  238. package/dist/src/formats/cys/session.d.ts +46 -7
  239. package/dist/src/formats/cys/session.d.ts.map +1 -1
  240. package/dist/src/formats/cys/session.js +98 -24
  241. package/dist/src/formats/cys/session.js.map +1 -1
  242. package/dist/src/formats/cys/tables.d.ts +9 -2
  243. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  244. package/dist/src/formats/cys/tables.js +29 -7
  245. package/dist/src/formats/cys/tables.js.map +1 -1
  246. package/dist/src/formats/dot/exporter.d.ts +42 -14
  247. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  248. package/dist/src/formats/dot/exporter.js +56 -29
  249. package/dist/src/formats/dot/exporter.js.map +1 -1
  250. package/dist/src/formats/dot/importer.d.ts +91 -29
  251. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  252. package/dist/src/formats/dot/importer.js +190 -39
  253. package/dist/src/formats/dot/importer.js.map +1 -1
  254. package/dist/src/formats/dot/index.d.ts +2 -1
  255. package/dist/src/formats/dot/index.d.ts.map +1 -1
  256. package/dist/src/formats/dot/index.js +2 -1
  257. package/dist/src/formats/dot/index.js.map +1 -1
  258. package/dist/src/formats/dot/names.d.ts +44 -11
  259. package/dist/src/formats/dot/names.d.ts.map +1 -1
  260. package/dist/src/formats/dot/names.js +44 -11
  261. package/dist/src/formats/dot/names.js.map +1 -1
  262. package/dist/src/formats/dot/tokenizer.d.ts +9 -2
  263. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
  264. package/dist/src/formats/dot/tokenizer.js +20 -5
  265. package/dist/src/formats/dot/tokenizer.js.map +1 -1
  266. package/dist/src/formats/gexf/exporter.d.ts +46 -15
  267. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  268. package/dist/src/formats/gexf/exporter.js +45 -15
  269. package/dist/src/formats/gexf/exporter.js.map +1 -1
  270. package/dist/src/formats/gexf/importer.d.ts +87 -23
  271. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  272. package/dist/src/formats/gexf/importer.js +471 -90
  273. package/dist/src/formats/gexf/importer.js.map +1 -1
  274. package/dist/src/formats/gexf/index.d.ts +84 -21
  275. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  276. package/dist/src/formats/gexf/index.js +80 -23
  277. package/dist/src/formats/gexf/index.js.map +1 -1
  278. package/dist/src/formats/gexf/schema.d.ts +67 -15
  279. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  280. package/dist/src/formats/gexf/schema.js +59 -13
  281. package/dist/src/formats/gexf/schema.js.map +1 -1
  282. package/dist/src/formats/gml/exporter.d.ts +69 -21
  283. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/gml/exporter.js +74 -29
  285. package/dist/src/formats/gml/exporter.js.map +1 -1
  286. package/dist/src/formats/gml/importer.d.ts +116 -25
  287. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  288. package/dist/src/formats/gml/importer.js +290 -61
  289. package/dist/src/formats/gml/importer.js.map +1 -1
  290. package/dist/src/formats/gml/index.d.ts +87 -24
  291. package/dist/src/formats/gml/index.d.ts.map +1 -1
  292. package/dist/src/formats/gml/index.js +79 -26
  293. package/dist/src/formats/gml/index.js.map +1 -1
  294. package/dist/src/formats/gml/syntax.d.ts +67 -18
  295. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  296. package/dist/src/formats/gml/syntax.js +108 -26
  297. package/dist/src/formats/gml/syntax.js.map +1 -1
  298. package/dist/src/formats/graphml/constants.d.ts +174 -44
  299. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  300. package/dist/src/formats/graphml/constants.js +165 -44
  301. package/dist/src/formats/graphml/constants.js.map +1 -1
  302. package/dist/src/formats/graphml/exporter.d.ts +17 -9
  303. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  304. package/dist/src/formats/graphml/exporter.js +33 -12
  305. package/dist/src/formats/graphml/exporter.js.map +1 -1
  306. package/dist/src/formats/graphml/importer.d.ts +19 -7
  307. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  308. package/dist/src/formats/graphml/importer.js +466 -39
  309. package/dist/src/formats/graphml/importer.js.map +1 -1
  310. package/dist/src/formats/graphml/index.d.ts +2 -1
  311. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  312. package/dist/src/formats/graphml/index.js +2 -1
  313. package/dist/src/formats/graphml/index.js.map +1 -1
  314. package/dist/src/formats/graphml/tree.d.ts +6 -2
  315. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  316. package/dist/src/formats/graphml/tree.js +6 -2
  317. package/dist/src/formats/graphml/tree.js.map +1 -1
  318. package/dist/src/formats/graphml/yfiles.d.ts +8 -3
  319. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  320. package/dist/src/formats/graphml/yfiles.js +36 -15
  321. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  322. package/dist/src/formats/json/dialect.d.ts +88 -24
  323. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  324. package/dist/src/formats/json/dialect.js +109 -19
  325. package/dist/src/formats/json/dialect.js.map +1 -1
  326. package/dist/src/formats/json/exporter.d.ts +134 -22
  327. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  328. package/dist/src/formats/json/exporter.js +135 -54
  329. package/dist/src/formats/json/exporter.js.map +1 -1
  330. package/dist/src/formats/json/importer.d.ts +173 -52
  331. package/dist/src/formats/json/importer.d.ts.map +1 -1
  332. package/dist/src/formats/json/importer.js +899 -220
  333. package/dist/src/formats/json/importer.js.map +1 -1
  334. package/dist/src/formats/json/index.d.ts +3 -2
  335. package/dist/src/formats/json/index.d.ts.map +1 -1
  336. package/dist/src/formats/json/index.js +3 -2
  337. package/dist/src/formats/json/index.js.map +1 -1
  338. package/dist/src/formats/json/obographs-export.d.ts +68 -0
  339. package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
  340. package/dist/src/formats/json/obographs-export.js +941 -0
  341. package/dist/src/formats/json/obographs-export.js.map +1 -0
  342. package/dist/src/formats/json/obographs.d.ts +26 -0
  343. package/dist/src/formats/json/obographs.d.ts.map +1 -1
  344. package/dist/src/formats/json/obographs.js +297 -80
  345. package/dist/src/formats/json/obographs.js.map +1 -1
  346. package/dist/src/formats/neo4j/exporter.d.ts +109 -21
  347. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  348. package/dist/src/formats/neo4j/exporter.js +238 -85
  349. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  350. package/dist/src/formats/neo4j/header.d.ts +17 -4
  351. package/dist/src/formats/neo4j/header.d.ts.map +1 -1
  352. package/dist/src/formats/neo4j/header.js +36 -4
  353. package/dist/src/formats/neo4j/header.js.map +1 -1
  354. package/dist/src/formats/neo4j/importer.d.ts +107 -27
  355. package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
  356. package/dist/src/formats/neo4j/importer.js +415 -63
  357. package/dist/src/formats/neo4j/importer.js.map +1 -1
  358. package/dist/src/formats/neo4j/index.d.ts +73 -23
  359. package/dist/src/formats/neo4j/index.d.ts.map +1 -1
  360. package/dist/src/formats/neo4j/index.js +65 -25
  361. package/dist/src/formats/neo4j/index.js.map +1 -1
  362. package/dist/src/formats/obo/exporter.d.ts +150 -0
  363. package/dist/src/formats/obo/exporter.d.ts.map +1 -0
  364. package/dist/src/formats/obo/exporter.js +1736 -0
  365. package/dist/src/formats/obo/exporter.js.map +1 -0
  366. package/dist/src/formats/obo/importer.d.ts +95 -19
  367. package/dist/src/formats/obo/importer.d.ts.map +1 -1
  368. package/dist/src/formats/obo/importer.js +475 -104
  369. package/dist/src/formats/obo/importer.js.map +1 -1
  370. package/dist/src/formats/obo/index.d.ts +6 -3
  371. package/dist/src/formats/obo/index.d.ts.map +1 -1
  372. package/dist/src/formats/obo/index.js +6 -3
  373. package/dist/src/formats/obo/index.js.map +1 -1
  374. package/dist/src/formats/obo/syntax.d.ts +108 -4
  375. package/dist/src/formats/obo/syntax.d.ts.map +1 -1
  376. package/dist/src/formats/obo/syntax.js +211 -34
  377. package/dist/src/formats/obo/syntax.js.map +1 -1
  378. package/dist/src/formats/pajek/exporter.d.ts +54 -16
  379. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  380. package/dist/src/formats/pajek/exporter.js +66 -34
  381. package/dist/src/formats/pajek/exporter.js.map +1 -1
  382. package/dist/src/formats/pajek/importer.d.ts +84 -22
  383. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  384. package/dist/src/formats/pajek/importer.js +303 -83
  385. package/dist/src/formats/pajek/importer.js.map +1 -1
  386. package/dist/src/formats/pajek/index.d.ts +2 -1
  387. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  388. package/dist/src/formats/pajek/index.js +2 -1
  389. package/dist/src/formats/pajek/index.js.map +1 -1
  390. package/dist/src/formats/pajek/syntax.d.ts +77 -14
  391. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  392. package/dist/src/formats/pajek/syntax.js +183 -51
  393. package/dist/src/formats/pajek/syntax.js.map +1 -1
  394. package/dist/src/formats/xgmml/columns.d.ts +1 -0
  395. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  396. package/dist/src/formats/xgmml/columns.js +4 -0
  397. package/dist/src/formats/xgmml/columns.js.map +1 -1
  398. package/dist/src/formats/xgmml/constants.d.ts +186 -56
  399. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  400. package/dist/src/formats/xgmml/constants.js +181 -57
  401. package/dist/src/formats/xgmml/constants.js.map +1 -1
  402. package/dist/src/formats/xgmml/document.d.ts +65 -11
  403. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  404. package/dist/src/formats/xgmml/document.js +157 -28
  405. package/dist/src/formats/xgmml/document.js.map +1 -1
  406. package/dist/src/formats/xgmml/emit.d.ts +61 -3
  407. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  408. package/dist/src/formats/xgmml/emit.js +129 -26
  409. package/dist/src/formats/xgmml/emit.js.map +1 -1
  410. package/dist/src/formats/xgmml/exporter.d.ts +13 -6
  411. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  412. package/dist/src/formats/xgmml/exporter.js +20 -21
  413. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  414. package/dist/src/formats/xgmml/importer.d.ts +33 -12
  415. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  416. package/dist/src/formats/xgmml/importer.js +35 -72
  417. package/dist/src/formats/xgmml/importer.js.map +1 -1
  418. package/dist/src/formats/xgmml/index.d.ts +1 -0
  419. package/dist/src/formats/xgmml/index.d.ts.map +1 -1
  420. package/dist/src/formats/xgmml/index.js +1 -0
  421. package/dist/src/formats/xgmml/index.js.map +1 -1
  422. package/dist/src/formats/xgmml/values.d.ts +8 -1
  423. package/dist/src/formats/xgmml/values.d.ts.map +1 -1
  424. package/dist/src/formats/xgmml/values.js +7 -2
  425. package/dist/src/formats/xgmml/values.js.map +1 -1
  426. package/dist/src/index.d.ts +23 -18
  427. package/dist/src/index.d.ts.map +1 -1
  428. package/dist/src/index.js +28 -16
  429. package/dist/src/index.js.map +1 -1
  430. package/dist/src/registry.d.ts +478 -92
  431. package/dist/src/registry.d.ts.map +1 -1
  432. package/dist/src/registry.js +807 -88
  433. package/dist/src/registry.js.map +1 -1
  434. package/dist/src/sniff.d.ts +61 -19
  435. package/dist/src/sniff.d.ts.map +1 -1
  436. package/dist/src/sniff.js +121 -29
  437. package/dist/src/sniff.js.map +1 -1
  438. package/dist/src/types.d.ts +362 -112
  439. package/dist/src/types.d.ts.map +1 -1
  440. package/dist/src/types.js +28 -7
  441. package/dist/src/types.js.map +1 -1
  442. package/dist/xgmml.js +2 -2
  443. package/docs/samples/README.md +25 -0
  444. package/docs/samples/got-edges.csv +353 -0
  445. package/docs/samples/got-network.graphml +1384 -0
  446. package/docs/samples/got-nodes.csv +108 -0
  447. package/docs/samples/got.cx +930 -0
  448. package/docs/samples/got.cx2 +465 -0
  449. package/docs/samples/got.gexf +471 -0
  450. package/docs/samples/got.gml +2650 -0
  451. package/docs/samples/got.json +2546 -0
  452. package/docs/samples/got.net +461 -0
  453. package/docs/samples/movies-nodes.csv +9 -0
  454. package/docs/samples/movies-rels.csv +8 -0
  455. package/docs/samples/networks.cys +0 -0
  456. package/docs/samples/proteins.xgmml +9 -0
  457. package/docs/samples/teams.gv +24 -0
  458. package/docs/samples/vehicles.obo +25 -0
  459. package/package.json +9 -4
  460. package/src/children.ts +18 -6
  461. package/src/common/attributes.ts +29 -11
  462. package/src/common/cell-budget.ts +11 -3
  463. package/src/common/choose.ts +89 -0
  464. package/src/common/codes.ts +490 -66
  465. package/src/common/compare.ts +472 -0
  466. package/src/common/cx-export.ts +432 -0
  467. package/src/common/declared-types.ts +38 -4
  468. package/src/common/direction.ts +78 -51
  469. package/src/common/escape.ts +33 -17
  470. package/src/common/export.ts +284 -47
  471. package/src/common/format.ts +30 -1
  472. package/src/common/ids.ts +14 -3
  473. package/src/common/input.ts +1057 -134
  474. package/src/common/json-elements.ts +1034 -198
  475. package/src/common/line-format.ts +249 -0
  476. package/src/common/lists.ts +6 -1
  477. package/src/common/ontology-export.ts +461 -0
  478. package/src/common/ontology.ts +31 -9
  479. package/src/common/options.ts +110 -15
  480. package/src/common/plural.ts +49 -0
  481. package/src/common/report.ts +168 -25
  482. package/src/common/temporal.ts +22 -5
  483. package/src/common/text.ts +62 -23
  484. package/src/common/weights.ts +74 -4
  485. package/src/common/writer.ts +37 -3
  486. package/src/common/xml.ts +477 -88
  487. package/src/common/zip.ts +169 -7
  488. package/src/formats/csv/exporter.ts +201 -46
  489. package/src/formats/csv/header.ts +50 -11
  490. package/src/formats/csv/importer.ts +1133 -245
  491. package/src/formats/csv/index.ts +106 -19
  492. package/src/formats/csv/records.ts +396 -122
  493. package/src/formats/csv/values.ts +1 -0
  494. package/src/formats/cx/exporter.ts +1483 -0
  495. package/src/formats/cx/importer.ts +888 -300
  496. package/src/formats/cx/index.ts +4 -3
  497. package/src/formats/cx2/exporter.ts +61 -338
  498. package/src/formats/cx2/importer.ts +317 -86
  499. package/src/formats/cx2/index.ts +2 -1
  500. package/src/formats/cys/constants.ts +62 -17
  501. package/src/formats/cys/exporter.ts +1368 -0
  502. package/src/formats/cys/importer.ts +659 -157
  503. package/src/formats/cys/index.ts +4 -2
  504. package/src/formats/cys/session.ts +139 -31
  505. package/src/formats/cys/tables.ts +47 -9
  506. package/src/formats/dot/exporter.ts +83 -37
  507. package/src/formats/dot/importer.ts +248 -54
  508. package/src/formats/dot/index.ts +2 -1
  509. package/src/formats/dot/names.ts +44 -11
  510. package/src/formats/dot/tokenizer.ts +25 -6
  511. package/src/formats/gexf/exporter.ts +57 -18
  512. package/src/formats/gexf/importer.ts +636 -105
  513. package/src/formats/gexf/index.ts +90 -21
  514. package/src/formats/gexf/schema.ts +67 -15
  515. package/src/formats/gml/exporter.ts +90 -36
  516. package/src/formats/gml/importer.ts +388 -67
  517. package/src/formats/gml/index.ts +85 -24
  518. package/src/formats/gml/syntax.ts +111 -26
  519. package/src/formats/graphml/constants.ts +178 -44
  520. package/src/formats/graphml/exporter.ts +52 -18
  521. package/src/formats/graphml/importer.ts +640 -60
  522. package/src/formats/graphml/index.ts +2 -1
  523. package/src/formats/graphml/tree.ts +6 -2
  524. package/src/formats/graphml/yfiles.ts +37 -15
  525. package/src/formats/json/dialect.ts +128 -29
  526. package/src/formats/json/exporter.ts +205 -68
  527. package/src/formats/json/importer.ts +1163 -253
  528. package/src/formats/json/index.ts +3 -1
  529. package/src/formats/json/obographs-export.ts +1197 -0
  530. package/src/formats/json/obographs.ts +353 -92
  531. package/src/formats/neo4j/exporter.ts +320 -101
  532. package/src/formats/neo4j/header.ts +44 -6
  533. package/src/formats/neo4j/importer.ts +512 -73
  534. package/src/formats/neo4j/index.ts +75 -23
  535. package/src/formats/obo/exporter.ts +2210 -0
  536. package/src/formats/obo/importer.ts +622 -109
  537. package/src/formats/obo/index.ts +6 -3
  538. package/src/formats/obo/syntax.ts +232 -37
  539. package/src/formats/pajek/exporter.ts +89 -41
  540. package/src/formats/pajek/importer.ts +407 -93
  541. package/src/formats/pajek/index.ts +2 -1
  542. package/src/formats/pajek/syntax.ts +213 -52
  543. package/src/formats/xgmml/columns.ts +10 -0
  544. package/src/formats/xgmml/constants.ts +183 -56
  545. package/src/formats/xgmml/document.ts +212 -34
  546. package/src/formats/xgmml/emit.ts +175 -34
  547. package/src/formats/xgmml/exporter.ts +35 -27
  548. package/src/formats/xgmml/importer.ts +64 -86
  549. package/src/formats/xgmml/index.ts +1 -0
  550. package/src/formats/xgmml/values.ts +11 -3
  551. package/src/index.ts +81 -11
  552. package/src/registry.ts +1121 -135
  553. package/src/sniff.ts +163 -32
  554. package/src/types.ts +385 -114
  555. package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
  556. package/dist/chunks/export-Bh60Dv-n.js +0 -582
  557. package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
  558. package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
  559. package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
  560. package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
  561. package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
  562. package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
  563. package/dist/chunks/importer-DET1tg6s.js.map +0 -1
  564. package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
  565. package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
  566. package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
  567. package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
  568. package/dist/chunks/importer-eUREhBGj.js.map +0 -1
  569. package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
  570. package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
  571. package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
  572. package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
  573. package/dist/chunks/ontology-BnrJ4I98.js +0 -113
  574. package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
  575. package/dist/chunks/records-dbRkxwaq.js.map +0 -1
  576. package/dist/chunks/report-B1z4WT9e.js +0 -2372
  577. package/dist/chunks/report-B1z4WT9e.js.map +0 -1
  578. package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
  579. package/dist/chunks/weights-Dzba96G3.js +0 -176
  580. package/dist/chunks/weights-Dzba96G3.js.map +0 -1
  581. package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
@@ -6,7 +6,7 @@
6
6
  * Cytoscape does, and the `.cys` importer reuses the same records for the network and view files
7
7
  * of a session.
8
8
  *
9
- * It recognises the five shapes of `research-xgmml.md` section 2: the 1.0 draft, the Cytoscape
9
+ * It recognizes the five shapes of `research-xgmml.md` section 2: the 1.0 draft, the Cytoscape
10
10
  * 2.x export and session, the 3.x export, the 3.x session network file (root `cy:registered="0"`)
11
11
  * and the 3.x session view file (root `cy:view="1"`).
12
12
  */
@@ -14,9 +14,12 @@
14
14
  import { escapeXmlAttribute, escapeXmlText } from "../../common/escape.js";
15
15
  import { type ImportReportBuilder } from "../../common/report.js";
16
16
  import { isWhitespace, localName, type XmlHandler } from "../../common/xml.js";
17
- import { XGMML_ISSUE, XGMML_NAMESPACE } from "./constants.js";
17
+ import { XGMML_ISSUE, XGMML_NAMESPACE, XLINK_NAMESPACE } from "./constants.js";
18
18
 
19
- /** One `<att>` and what it holds. */
19
+ /**
20
+ * One `<att>` and what it holds.
21
+ * @category Plugin helpers
22
+ */
20
23
  export interface AttRec {
21
24
  /** The `name` (else `label`) attribute, or null. */
22
25
  name: string | null;
@@ -48,7 +51,10 @@ export interface AttRec {
48
51
  readonly namespace?: string | null | undefined;
49
52
  }
50
53
 
51
- /** A `<node>`. */
54
+ /**
55
+ * A `<node>`.
56
+ * @category Plugin helpers
57
+ */
52
58
  export interface NodeRec {
53
59
  readonly kind: "node";
54
60
  /** The id (the label when the id is missing), or null for an `xlink:href` reference. */
@@ -79,7 +85,10 @@ export interface NodeRec {
79
85
  readonly viewId: string | null;
80
86
  }
81
87
 
82
- /** An `<edge>`. */
88
+ /**
89
+ * An `<edge>`.
90
+ * @category Plugin helpers
91
+ */
83
92
  export interface EdgeRec {
84
93
  readonly kind: "edge";
85
94
  /** The id attribute, or null. */
@@ -111,7 +120,10 @@ export interface EdgeRec {
111
120
  readonly viewId: string | null;
112
121
  }
113
122
 
114
- /** A `<graph>`: the root, a subnetwork, a group or a nested-network pointer. */
123
+ /**
124
+ * A `<graph>`: the root, a subnetwork, a group or a nested-network pointer.
125
+ * @category Plugin helpers
126
+ */
115
127
  export interface GraphRec {
116
128
  /** The id attribute, or null. */
117
129
  readonly id: string | null;
@@ -139,7 +151,10 @@ export interface GraphRec {
139
151
  readonly line: number;
140
152
  }
141
153
 
142
- /** A parsed document. */
154
+ /**
155
+ * A parsed document.
156
+ * @category Plugin helpers
157
+ */
143
158
  export interface XgmmlDocument {
144
159
  /** The root graph. */
145
160
  readonly root: GraphRec;
@@ -157,6 +172,8 @@ export interface XgmmlDocument {
157
172
  readonly rdf: Record<string, string>;
158
173
  /** The serialized `networkMetadata` RDF, or null. */
159
174
  readonly rdfXml: string | null;
175
+ /** The DOCTYPE declaration as written, or null. */
176
+ readonly doctype: string | null;
160
177
  }
161
178
 
162
179
  /** What the parser keeps about one open element. */
@@ -167,7 +184,14 @@ type Frame =
167
184
  | { readonly kind: "att"; readonly att: AttRec; readonly owner: "graph" | "node" | "edge" | "graphics" | "att" }
168
185
  | { readonly kind: "graphics"; readonly target: GraphicsTarget }
169
186
  | { readonly kind: "line"; readonly points: Record<string, string>[] }
170
- | { readonly kind: "capture"; readonly att: AttRec; depth: number }
187
+ | {
188
+ readonly kind: "capture";
189
+ readonly att: AttRec;
190
+ depth: number;
191
+ /** Where the captured element starts in `att.xml`, and the namespaces in scope there. */
192
+ start: number;
193
+ scope: ReadonlyMap<string, string>;
194
+ }
171
195
  | { readonly kind: "skip" };
172
196
 
173
197
  /** What a `<graphics>` writes into. */
@@ -214,35 +238,46 @@ const TRUE_TEXT = /^(1|true|yes)$/i;
214
238
  * Whether a Cytoscape flag text is true.
215
239
  * @param text - the text, or undefined
216
240
  * @returns true for 1, true or yes in any case
241
+ * @category Plugin helpers
217
242
  */
218
243
  export function isCyTrue(text: string | null | undefined): boolean {
219
244
  return text !== null && text !== undefined && TRUE_TEXT.test(text.trim());
220
245
  }
221
246
 
222
247
  /**
223
- * The name an XML attribute is known by, its `xlink` prefix normalised whatever prefix the file
224
- * binds XLink to (galFiltered.xgmml uses `ns1`).
248
+ * The name an XML attribute is known by, its `xlink` prefix normalized whatever prefix the file
249
+ * binds XLink to (galFiltered.xgmml uses `ns1`), on the element itself or on any ancestor; an
250
+ * unbound `xlink:` prefix is XLink too.
225
251
  * @param name - the attribute name as written
226
- * @param xlinkPrefixes - the prefixes bound to the XLink namespace
252
+ * @param scope - the namespace prefixes in scope (prefix to URI, "" for the default)
227
253
  * @returns the name with `xlink:` for XLink attributes
228
254
  */
229
- function normaliseName(name: string, xlinkPrefixes: ReadonlySet<string>): string {
255
+ function normaliseName(name: string, scope: ReadonlyMap<string, string>): string {
230
256
  const colon = name.indexOf(":");
231
- if (colon > 0 && xlinkPrefixes.has(name.slice(0, colon))) {
257
+ if (colon <= 0) {
258
+ return name;
259
+ }
260
+ const prefix = name.slice(0, colon);
261
+ if (prefix === "xlink" || scope.get(prefix) === XLINK_NAMESPACE) {
232
262
  return `xlink:${name.slice(colon + 1)}`;
233
263
  }
234
264
  return name;
235
265
  }
236
266
 
267
+ /** The namespaces in scope outside the root element. */
268
+ const NO_SCOPE: ReadonlyMap<string, string> = new Map();
269
+
237
270
  /**
238
271
  * The tokenizer handler that builds an XgmmlDocument.
272
+ * @category Plugin helpers
239
273
  */
240
274
  export class XgmmlParser implements XmlHandler {
241
275
  private readonly report: ImportReportBuilder;
242
276
 
243
277
  private readonly frames: Frame[] = [];
244
278
 
245
- private readonly xlinkPrefixes = new Set<string>(["xlink"]);
279
+ /** The namespace prefixes in scope at each open element (prefix to URI, "" for the default). */
280
+ private readonly scopes: ReadonlyMap<string, string>[] = [];
246
281
 
247
282
  private rootGraph: GraphRec | null = null;
248
283
 
@@ -263,6 +298,8 @@ export class XgmmlParser implements XmlHandler {
263
298
 
264
299
  private rdfXml: string | null = null;
265
300
 
301
+ private doctypeText: string | null = null;
302
+
266
303
  /**
267
304
  * Create a parser.
268
305
  * @param report - the report issues are recorded in
@@ -289,9 +326,18 @@ export class XgmmlParser implements XmlHandler {
289
326
  xgmmlNamespace: this.xgmmlNamespace,
290
327
  rdf: this.rdf,
291
328
  rdfXml: this.rdfXml,
329
+ doctype: this.doctypeText,
292
330
  };
293
331
  }
294
332
 
333
+ /**
334
+ * The DOCTYPE declaration.
335
+ * @param text - the declaration as written
336
+ */
337
+ doctype(text: string): void {
338
+ this.doctypeText ??= text;
339
+ }
340
+
295
341
  /**
296
342
  * An element starts.
297
343
  * @param rawName - the element name as written
@@ -299,6 +345,7 @@ export class XgmmlParser implements XmlHandler {
299
345
  * @param line - the line
300
346
  */
301
347
  start(rawName: string, rawAttrs: ReadonlyMap<string, string>, line: number): void {
348
+ this.enterScope(rawAttrs);
302
349
  const top = this.frames.length === 0 ? null : this.frames[this.frames.length - 1];
303
350
  if (top === null) {
304
351
  this.startRoot(rawName, rawAttrs, line);
@@ -312,8 +359,9 @@ export class XgmmlParser implements XmlHandler {
312
359
  this.capture(top, rawName, rawAttrs);
313
360
  return;
314
361
  }
315
- const attrs = this.normalise(rawAttrs);
316
- const name = localName(rawName);
362
+ const attrs = this.normalize(rawAttrs);
363
+ // an element of another namespace keeps its prefix, so no XGMML element name matches it
364
+ const name = this.isXgmmlName(rawName) ? localName(rawName) : rawName;
317
365
  switch (top.kind) {
318
366
  case "graph":
319
367
  this.startInGraph(top.graph, rawName, name, attrs, line);
@@ -351,6 +399,7 @@ export class XgmmlParser implements XmlHandler {
351
399
  * @param _line - the line
352
400
  */
353
401
  end(name: string, _line: number): void {
402
+ this.scopes.pop();
354
403
  const frame = this.frames.pop();
355
404
  const below = this.frames.length === 0 ? null : this.frames[this.frames.length - 1];
356
405
  switch (frame?.kind) {
@@ -359,7 +408,11 @@ export class XgmmlParser implements XmlHandler {
359
408
  frame.depth--;
360
409
  if (frame.depth > 0) {
361
410
  this.frames.push(frame);
362
- } else if (frame.att.name === "networkMetadata") {
411
+ this.rdfElement = null;
412
+ return;
413
+ }
414
+ frame.att.xml = bindPrefixes(frame.att.xml, frame.start, frame.scope);
415
+ if (frame.att.name === "networkMetadata") {
363
416
  this.rdfXml = frame.att.xml;
364
417
  }
365
418
  this.rdfElement = null;
@@ -411,15 +464,42 @@ export class XgmmlParser implements XmlHandler {
411
464
 
412
465
  // ------------------------------------------------------------------ structure
413
466
 
467
+ /**
468
+ * Open the namespace scope of an element: its parent's, plus the prefixes it declares.
469
+ * @param attrs - the element's attributes as written
470
+ */
471
+ private enterScope(attrs: ReadonlyMap<string, string>): void {
472
+ const parent = this.scopes.at(-1) ?? NO_SCOPE;
473
+ let scope = parent;
474
+ for (const [key, value] of attrs) {
475
+ if (key === "xmlns" || key.startsWith("xmlns:")) {
476
+ if (scope === parent) {
477
+ scope = new Map(parent);
478
+ }
479
+ (scope as Map<string, string>).set(key === "xmlns" ? "" : key.slice(6), value);
480
+ }
481
+ }
482
+ this.scopes.push(scope);
483
+ }
484
+
485
+ /**
486
+ * The namespace prefixes in scope at the innermost open element.
487
+ * @returns prefix to URI
488
+ */
489
+ private get scope(): ReadonlyMap<string, string> {
490
+ return this.scopes.at(-1) ?? NO_SCOPE;
491
+ }
492
+
414
493
  /**
415
494
  * The XML attribute map with every XLink prefix written `xlink:`.
416
495
  * @param attrs - the attributes as written
417
- * @returns the normalised map
496
+ * @returns the normalized map
418
497
  */
419
- private normalise(attrs: ReadonlyMap<string, string>): Map<string, string> {
498
+ private normalize(attrs: ReadonlyMap<string, string>): Map<string, string> {
420
499
  const out = new Map<string, string>();
500
+ const { scope } = this;
421
501
  for (const [key, value] of attrs) {
422
- out.set(normaliseName(key, this.xlinkPrefixes), value);
502
+ out.set(normaliseName(key, scope), value);
423
503
  }
424
504
  return out;
425
505
  }
@@ -433,10 +513,7 @@ export class XgmmlParser implements XmlHandler {
433
513
  private startRoot(rawName: string, rawAttrs: ReadonlyMap<string, string>, line: number): void {
434
514
  const local = localName(rawName);
435
515
  const prefix = rawName.includes(":") ? rawName.slice(0, rawName.indexOf(":")) : null;
436
- for (const [key, value] of rawAttrs) {
437
- if (key.startsWith("xmlns:") && value === "http://www.w3.org/1999/xlink") {
438
- this.xlinkPrefixes.add(key.slice(6));
439
- }
516
+ for (const key of rawAttrs.keys()) {
440
517
  if (key === "xmlns:cy" || key.startsWith("cy:")) {
441
518
  this.cytoscape = true;
442
519
  }
@@ -451,7 +528,7 @@ export class XgmmlParser implements XmlHandler {
451
528
  { line },
452
529
  );
453
530
  }
454
- const graph = this.newGraph(this.normalise(rawAttrs), line, null, null);
531
+ const graph = this.newGraph(this.normalize(rawAttrs), line, null, null);
455
532
  this.rootGraph = graph;
456
533
  this.frames.push({ kind: "graph", graph });
457
534
  }
@@ -524,7 +601,7 @@ export class XgmmlParser implements XmlHandler {
524
601
  return;
525
602
  }
526
603
  case "graphics":
527
- this.beginGraphics(graph, attrs);
604
+ this.beginGraphics(graph, attrs, line);
528
605
  return;
529
606
  default:
530
607
  this.unknownElement(rawName, line);
@@ -554,7 +631,7 @@ export class XgmmlParser implements XmlHandler {
554
631
  return;
555
632
  }
556
633
  case "graphics":
557
- this.beginGraphics(element, attrs);
634
+ this.beginGraphics(element, attrs, line);
558
635
  return;
559
636
  default:
560
637
  this.unknownElement(rawName, line);
@@ -591,20 +668,31 @@ export class XgmmlParser implements XmlHandler {
591
668
  }
592
669
  // a second foreign element of the same att is appended to the first
593
670
  att.xml ??= "";
594
- const capture: Extract<Frame, { kind: "capture" }> = { kind: "capture", att, depth: 0 };
671
+ const capture: Extract<Frame, { kind: "capture" }> = {
672
+ kind: "capture",
673
+ att,
674
+ depth: 0,
675
+ start: att.xml.length,
676
+ scope: this.scope,
677
+ };
595
678
  this.frames.push(capture);
596
679
  this.capture(capture, rawName, attrs);
597
680
  }
598
681
 
599
682
  /**
600
- * Whether an element name inside an att is XGMML's own (unprefixed, or with the root's prefix,
601
- * as in a document whose root is `<xgmml:graph>`) rather than foreign XML such as `rdf:RDF`.
683
+ * Whether an element name is XGMML's own (unprefixed, with the root's prefix as in a document
684
+ * whose root is `<xgmml:graph>`, or with any prefix bound to the XGMML namespace) rather than
685
+ * foreign XML such as `rdf:RDF` or `svg:node`.
602
686
  * @param rawName - the name as written
603
687
  * @returns true for an XGMML element name
604
688
  */
605
689
  private isXgmmlName(rawName: string): boolean {
606
690
  const colon = rawName.indexOf(":");
607
- return colon < 0 || (this.rootPrefix !== null && rawName.slice(0, colon) === this.rootPrefix);
691
+ if (colon < 0) {
692
+ return true;
693
+ }
694
+ const prefix = rawName.slice(0, colon);
695
+ return prefix === this.rootPrefix || this.scope.get(prefix) === XGMML_NAMESPACE;
608
696
  }
609
697
 
610
698
  /**
@@ -681,6 +769,9 @@ export class XgmmlParser implements XmlHandler {
681
769
  const labelAttr = attrs.get("label") ?? null;
682
770
  const nameAttr = attrs.get("name") ?? null;
683
771
  const label = labelAttr ?? nameAttr;
772
+ if (href !== null && id !== null) {
773
+ this.idAndHref("node", id, href, line);
774
+ }
684
775
  if (href === null && id === null) {
685
776
  if (label === null || label.length === 0) {
686
777
  this.report.counts.skippedNodes++;
@@ -730,9 +821,13 @@ export class XgmmlParser implements XmlHandler {
730
821
  */
731
822
  private beginEdge(graph: GraphRec, attrs: Map<string, string>, line: number): void {
732
823
  const href = attrs.get("xlink:href") ?? null;
824
+ const id = attrs.get("id") ?? null;
825
+ if (href !== null && id !== null) {
826
+ this.idAndHref("edge", id, href, line);
827
+ }
733
828
  const edge: EdgeRec = {
734
829
  kind: "edge",
735
- id: href === null ? (attrs.get("id") ?? null) : null,
830
+ id: href === null ? id : null,
736
831
  href,
737
832
  source: attrs.get("source") ?? null,
738
833
  target: attrs.get("target") ?? null,
@@ -754,6 +849,22 @@ export class XgmmlParser implements XmlHandler {
754
849
  this.frames.push({ kind: "edge", edge });
755
850
  }
756
851
 
852
+ /**
853
+ * W_XGMML_ID_AND_HREF: an element that both declares an id and references another element.
854
+ * @param kind - node or edge
855
+ * @param id - the id
856
+ * @param href - the reference
857
+ * @param line - the line
858
+ */
859
+ private idAndHref(kind: string, id: string, href: string, line: number): void {
860
+ this.report.warning(
861
+ "validation-error",
862
+ XGMML_ISSUE.ID_AND_HREF,
863
+ `<${kind}> has both id "${id}" and xlink:href "${href}"; it is read as a reference to ${href} and the id is not used`,
864
+ { line, element: id },
865
+ );
866
+ }
867
+
757
868
  // ------------------------------------------------------------------ atts
758
869
 
759
870
  /**
@@ -818,7 +929,18 @@ export class XgmmlParser implements XmlHandler {
818
929
  frame.att.xml = `${frame.att.xml ?? ""}${tag}>`;
819
930
  frame.depth++;
820
931
  if (frame.att.name === "networkMetadata") {
821
- this.rdfElement = localName(rawName);
932
+ const field = localName(rawName);
933
+ this.rdfElement = field;
934
+ if (this.rdf[field] !== undefined) {
935
+ // a second <dc:title>: the first is kept, the two are never joined
936
+ this.rdfElement = null;
937
+ this.report.warning(
938
+ "validation-error",
939
+ XGMML_ISSUE.DUPLICATE_ATTRIBUTE,
940
+ `the network metadata gives <${rawName}> twice; the first ("${this.rdf[field]}") is kept`,
941
+ { line: frame.att.line, element: field },
942
+ );
943
+ }
822
944
  }
823
945
  }
824
946
 
@@ -842,13 +964,20 @@ export class XgmmlParser implements XmlHandler {
842
964
  * attribute is kept as written, merged key by key with an earlier `<graphics>`.
843
965
  * @param target - the node, edge or graph
844
966
  * @param attrs - its attributes
967
+ * @param line - the line
845
968
  */
846
- private beginGraphics(target: GraphicsTarget, attrs: Map<string, string>): void {
969
+ private beginGraphics(target: GraphicsTarget, attrs: Map<string, string>, line: number): void {
847
970
  const graphics: Record<string, unknown> = { ...(target.graphics ?? {}) };
848
971
  for (const [key, value] of attrs) {
849
972
  if ("x" in target && (key === "x" || key === "y" || key === "z")) {
973
+ if (target[key] !== null && target[key] !== undefined) {
974
+ this.duplicateGraphics(key, line);
975
+ }
850
976
  target[key] = value;
851
977
  } else if (key !== "xmlns" && !key.startsWith("xmlns:")) {
978
+ if (key in graphics) {
979
+ this.duplicateGraphics(key, line);
980
+ }
852
981
  graphics[key] = value;
853
982
  }
854
983
  }
@@ -914,8 +1043,26 @@ export class XgmmlParser implements XmlHandler {
914
1043
  );
915
1044
  return;
916
1045
  }
1046
+ if (target.graphics !== null && att.name in target.graphics) {
1047
+ this.duplicateGraphics(att.name, att.line);
1048
+ }
917
1049
  target.graphics = { ...(target.graphics ?? {}), [att.name]: attJson(att) };
918
1050
  }
1051
+
1052
+ /**
1053
+ * W_DUPLICATE_ATTRIBUTE for a graphics property given twice on one element (once per name).
1054
+ * @param key - the property
1055
+ * @param line - the line
1056
+ */
1057
+ private duplicateGraphics(key: string, line: number): void {
1058
+ this.report.warnOnce(
1059
+ "validation-error",
1060
+ XGMML_ISSUE.DUPLICATE_ATTRIBUTE,
1061
+ `the graphics property "${key}" is given twice on one element; the later value is kept`,
1062
+ { line, element: key },
1063
+ `${XGMML_ISSUE.DUPLICATE_ATTRIBUTE}:graphics:${key}`,
1064
+ );
1065
+ }
919
1066
  }
920
1067
 
921
1068
  /**
@@ -923,6 +1070,7 @@ export class XgmmlParser implements XmlHandler {
923
1070
  * the parent's name (Cytoscape 3 lists), or are several that share one name (2.x bend handles).
924
1071
  * @param att - the att
925
1072
  * @returns true for a list
1073
+ * @category Plugin helpers
926
1074
  */
927
1075
  export function isListLike(att: AttRec): boolean {
928
1076
  const names = new Set(att.children.map((c) => c.name));
@@ -939,6 +1087,7 @@ export function isListLike(att: AttRec): boolean {
939
1087
  * else its other XML attributes (a 2.x bend handle's x and y), else null.
940
1088
  * @param att - the att
941
1089
  * @returns the value
1090
+ * @category Plugin helpers
942
1091
  */
943
1092
  export function attJson(att: AttRec): unknown {
944
1093
  if (att.children.length === 0) {
@@ -957,6 +1106,35 @@ export function attJson(att: AttRec): unknown {
957
1106
  return out;
958
1107
  }
959
1108
 
1109
+ /**
1110
+ * Declare on a captured element the namespace prefixes the captured XML uses but does not bind
1111
+ * itself, so the stored XML is namespace-well-formed on its own.
1112
+ * @param xml - the captured XML of the att
1113
+ * @param start - where the captured element starts in it
1114
+ * @param scope - the namespaces in scope at the captured element
1115
+ * @returns the XML with the declarations added to the captured element's start tag
1116
+ */
1117
+ function bindPrefixes(xml: string, start: number, scope: ReadonlyMap<string, string>): string {
1118
+ const segment = xml.slice(start);
1119
+ const used = new Set<string>();
1120
+ for (const match of segment.matchAll(/<\/?([A-Za-z_][\w.-]*):|\s([A-Za-z_][\w.-]*):[\w.-]+="/g)) {
1121
+ used.add(match[1] ?? match[2]);
1122
+ }
1123
+ let declarations = "";
1124
+ for (const prefix of used) {
1125
+ const uri = scope.get(prefix);
1126
+ if (prefix !== "xmlns" && prefix !== "xml" && uri !== undefined && !segment.includes(` xmlns:${prefix}="`)) {
1127
+ declarations += ` xmlns:${prefix}="${escapeXmlAttribute(uri)}"`;
1128
+ }
1129
+ }
1130
+ if (declarations.length === 0) {
1131
+ return xml;
1132
+ }
1133
+ const nameEnd = xml.slice(start).search(/[\s>]/);
1134
+ const at = start + (nameEnd < 0 ? segment.length : nameEnd);
1135
+ return `${xml.slice(0, at)}${declarations}${xml.slice(at)}`;
1136
+ }
1137
+
960
1138
  /**
961
1139
  * The XML attributes of an element the parser does not read itself, without namespace
962
1140
  * declarations.