@graphty/graph-io 0.3.48 → 0.3.49

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 (570) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-Bzn3L-je.js.map} +1 -1
  3. package/dist/chunks/bends-BGXjv_U4.js +129 -0
  4. package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
  5. package/dist/chunks/{block-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
  6. package/dist/chunks/block-iptrlMBb.js.map +1 -0
  7. package/dist/chunks/choose-CczZJaX_.js +717 -0
  8. package/dist/chunks/choose-CczZJaX_.js.map +1 -0
  9. package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
  15. package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
  16. package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
  17. package/dist/chunks/{credentials-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
  18. package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
  19. package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
  20. package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
  24. package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
  26. package/dist/chunks/emit-BwHQkZle.js.map +1 -0
  27. package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
  28. package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
  29. package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
  30. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  31. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  32. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  33. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
  34. package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
  35. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
  36. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
  39. package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
  40. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-nDfxIK5D.js.map} +1 -1
  41. package/dist/chunks/format-BXiAb-1h.js +408 -0
  42. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  43. package/dist/chunks/{generic-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
  44. package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
  45. package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
  46. package/dist/chunks/importer-B92x1xY5.js.map +1 -0
  47. package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
  48. package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
  49. package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
  50. package/dist/chunks/importer-DaLTjbds.js.map +1 -0
  51. package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
  52. package/dist/chunks/importer-GREKMdIf.js.map +1 -0
  53. package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
  54. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
  55. package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
  56. package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
  57. package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
  58. package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
  59. package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
  60. package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
  61. package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
  62. package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  63. package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
  64. package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
  65. package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
  66. package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  67. package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
  68. package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
  69. package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
  70. package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
  71. package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
  72. package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
  74. package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
  76. package/dist/chunks/styles-CCs214_3.js.map +1 -0
  77. package/dist/chunks/styles-Cm62yyQX.js +2812 -0
  78. package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
  79. package/dist/chunks/styles-DPQQIig4.js +1928 -0
  80. package/dist/chunks/styles-DPQQIig4.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
  82. package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
  83. package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
  84. package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
  85. package/dist/csv.js +7 -7
  86. package/dist/cx.js +2 -2
  87. package/dist/cx2.js +2 -2
  88. package/dist/cys.js +1 -1
  89. package/dist/dot.js +5 -4
  90. package/dist/dot.js.map +1 -1
  91. package/dist/gexf.js +42 -12
  92. package/dist/gexf.js.map +1 -1
  93. package/dist/gml.js +847 -193
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +232 -220
  96. package/dist/graph-io.js.map +1 -1
  97. package/dist/graphml.js +3 -3
  98. package/dist/json.js +3 -2
  99. package/dist/neo4j.js +6 -6
  100. package/dist/obo.js +1 -1
  101. package/dist/pajek.js +1 -1
  102. package/dist/positions.js +45 -3
  103. package/dist/positions.js.map +1 -1
  104. package/dist/sources-cypher.js +138 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +16 -6
  108. package/dist/sources-rest.js.map +1 -1
  109. package/dist/sources-sparql.d.ts +1 -0
  110. package/dist/sources-sparql.js +405 -0
  111. package/dist/sources-sparql.js.map +1 -0
  112. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  113. package/dist/src/formats/cx/importer.js +5 -1
  114. package/dist/src/formats/cx/importer.js.map +1 -1
  115. package/dist/src/formats/cx/styles.d.ts +24 -1
  116. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  117. package/dist/src/formats/cx/styles.js +117 -11
  118. package/dist/src/formats/cx/styles.js.map +1 -1
  119. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  120. package/dist/src/formats/cx2/importer.js +1 -0
  121. package/dist/src/formats/cx2/importer.js.map +1 -1
  122. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  123. package/dist/src/formats/cx2/styles.js +3 -1
  124. package/dist/src/formats/cx2/styles.js.map +1 -1
  125. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cys/importer.js +1 -0
  127. package/dist/src/formats/cys/importer.js.map +1 -1
  128. package/dist/src/formats/cys/styles.d.ts +2 -0
  129. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cys/styles.js +15 -7
  131. package/dist/src/formats/cys/styles.js.map +1 -1
  132. package/dist/src/formats/dot/drawing.d.ts +98 -0
  133. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  134. package/dist/src/formats/dot/drawing.js +734 -0
  135. package/dist/src/formats/dot/drawing.js.map +1 -0
  136. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  137. package/dist/src/formats/dot/importer.js +108 -31
  138. package/dist/src/formats/dot/importer.js.map +1 -1
  139. package/dist/src/formats/dot/label-places.d.ts +34 -0
  140. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  141. package/dist/src/formats/dot/label-places.js +179 -0
  142. package/dist/src/formats/dot/label-places.js.map +1 -0
  143. package/dist/src/formats/dot/record.d.ts +50 -0
  144. package/dist/src/formats/dot/record.d.ts.map +1 -0
  145. package/dist/src/formats/dot/record.js +275 -0
  146. package/dist/src/formats/dot/record.js.map +1 -0
  147. package/dist/src/formats/dot/styles.d.ts +62 -2
  148. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  149. package/dist/src/formats/dot/styles.js +1454 -119
  150. package/dist/src/formats/dot/styles.js.map +1 -1
  151. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  152. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  153. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  154. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  155. package/dist/src/formats/gexf/importer.d.ts +7 -0
  156. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  157. package/dist/src/formats/gexf/importer.js +41 -5
  158. package/dist/src/formats/gexf/importer.js.map +1 -1
  159. package/dist/src/formats/gexf/preview.d.ts +77 -0
  160. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  161. package/dist/src/formats/gexf/preview.js +191 -0
  162. package/dist/src/formats/gexf/preview.js.map +1 -0
  163. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  164. package/dist/src/formats/gexf/schema.js +2 -1
  165. package/dist/src/formats/gexf/schema.js.map +1 -1
  166. package/dist/src/formats/gexf/styles.d.ts +58 -31
  167. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  168. package/dist/src/formats/gexf/styles.js +848 -225
  169. package/dist/src/formats/gexf/styles.js.map +1 -1
  170. package/dist/src/formats/gml/importer.d.ts +5 -2
  171. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  172. package/dist/src/formats/gml/importer.js +258 -71
  173. package/dist/src/formats/gml/importer.js.map +1 -1
  174. package/dist/src/formats/gml/index.d.ts +1 -1
  175. package/dist/src/formats/gml/index.d.ts.map +1 -1
  176. package/dist/src/formats/gml/index.js +1 -1
  177. package/dist/src/formats/gml/index.js.map +1 -1
  178. package/dist/src/formats/gml/positions.d.ts +7 -0
  179. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  180. package/dist/src/formats/gml/positions.js +29 -7
  181. package/dist/src/formats/gml/positions.js.map +1 -1
  182. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  183. package/dist/src/formats/gml/styles.js +753 -101
  184. package/dist/src/formats/gml/styles.js.map +1 -1
  185. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  186. package/dist/src/formats/graphml/styles-plain.js +6 -10
  187. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  188. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  189. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  190. package/dist/src/formats/graphml/styles-yed.js +692 -161
  191. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  192. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  193. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  194. package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
  195. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  196. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  197. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/yfiles.js +16 -6
  199. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  200. package/dist/src/formats/json/dialect.d.ts +3 -2
  201. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  202. package/dist/src/formats/json/dialect.js +39 -5
  203. package/dist/src/formats/json/dialect.js.map +1 -1
  204. package/dist/src/formats/json/importer.d.ts +13 -2
  205. package/dist/src/formats/json/importer.d.ts.map +1 -1
  206. package/dist/src/formats/json/importer.js +42 -6
  207. package/dist/src/formats/json/importer.js.map +1 -1
  208. package/dist/src/formats/json/index.d.ts +1 -1
  209. package/dist/src/formats/json/index.d.ts.map +1 -1
  210. package/dist/src/formats/json/index.js +1 -1
  211. package/dist/src/formats/json/index.js.map +1 -1
  212. package/dist/src/formats/json/positions.d.ts +5 -2
  213. package/dist/src/formats/json/positions.d.ts.map +1 -1
  214. package/dist/src/formats/json/positions.js +20 -4
  215. package/dist/src/formats/json/positions.js.map +1 -1
  216. package/dist/src/formats/json/styles.d.ts +12 -1
  217. package/dist/src/formats/json/styles.d.ts.map +1 -1
  218. package/dist/src/formats/json/styles.js +1755 -136
  219. package/dist/src/formats/json/styles.js.map +1 -1
  220. package/dist/src/formats/pajek/draw.d.ts +96 -0
  221. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  222. package/dist/src/formats/pajek/draw.js +372 -0
  223. package/dist/src/formats/pajek/draw.js.map +1 -0
  224. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  225. package/dist/src/formats/pajek/exporter.js +70 -51
  226. package/dist/src/formats/pajek/exporter.js.map +1 -1
  227. package/dist/src/formats/pajek/importer.d.ts +9 -0
  228. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  229. package/dist/src/formats/pajek/importer.js +233 -102
  230. package/dist/src/formats/pajek/importer.js.map +1 -1
  231. package/dist/src/formats/pajek/index.d.ts +1 -0
  232. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  233. package/dist/src/formats/pajek/index.js.map +1 -1
  234. package/dist/src/formats/pajek/styles.d.ts +15 -7
  235. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  236. package/dist/src/formats/pajek/styles.js +1278 -114
  237. package/dist/src/formats/pajek/styles.js.map +1 -1
  238. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  239. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  240. package/dist/src/formats/pajek/syntax.js +26 -2
  241. package/dist/src/formats/pajek/syntax.js.map +1 -1
  242. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  243. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  244. package/dist/src/formats/xgmml/emit.js +65 -5
  245. package/dist/src/formats/xgmml/emit.js.map +1 -1
  246. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  247. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  248. package/dist/src/formats/xgmml/styles.js +277 -60
  249. package/dist/src/formats/xgmml/styles.js.map +1 -1
  250. package/dist/src/index.d.ts +4 -3
  251. package/dist/src/index.d.ts.map +1 -1
  252. package/dist/src/index.js +4 -3
  253. package/dist/src/index.js.map +1 -1
  254. package/dist/src/positions/convert.d.ts.map +1 -1
  255. package/dist/src/positions/convert.js +11 -1
  256. package/dist/src/positions/convert.js.map +1 -1
  257. package/dist/src/positions/extract.d.ts.map +1 -1
  258. package/dist/src/positions/extract.js +53 -1
  259. package/dist/src/positions/extract.js.map +1 -1
  260. package/dist/src/positions/index.d.ts +1 -1
  261. package/dist/src/positions/index.d.ts.map +1 -1
  262. package/dist/src/positions/types.d.ts +59 -0
  263. package/dist/src/positions/types.d.ts.map +1 -1
  264. package/dist/src/sources/builtins.d.ts +1 -1
  265. package/dist/src/sources/builtins.d.ts.map +1 -1
  266. package/dist/src/sources/builtins.js +8 -2
  267. package/dist/src/sources/builtins.js.map +1 -1
  268. package/dist/src/sources/context.d.ts.map +1 -1
  269. package/dist/src/sources/context.js +1 -0
  270. package/dist/src/sources/context.js.map +1 -1
  271. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  272. package/dist/src/sources/cypher/descriptor.js +5 -0
  273. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  274. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  275. package/dist/src/sources/cypher/index.js +124 -18
  276. package/dist/src/sources/cypher/index.js.map +1 -1
  277. package/dist/src/sources/cypher/params.d.ts +1 -1
  278. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  279. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  280. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  281. package/dist/src/sources/cypher/query-builder.js +31 -0
  282. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  283. package/dist/src/sources/ids.d.ts +5 -0
  284. package/dist/src/sources/ids.d.ts.map +1 -1
  285. package/dist/src/sources/ids.js +5 -0
  286. package/dist/src/sources/ids.js.map +1 -1
  287. package/dist/src/sources/params.d.ts +3 -0
  288. package/dist/src/sources/params.d.ts.map +1 -1
  289. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  290. package/dist/src/sources/rest/descriptor.js +5 -0
  291. package/dist/src/sources/rest/descriptor.js.map +1 -1
  292. package/dist/src/sources/rest/source.d.ts.map +1 -1
  293. package/dist/src/sources/rest/source.js +15 -0
  294. package/dist/src/sources/rest/source.js.map +1 -1
  295. package/dist/src/sources/sigv4.d.ts +5 -3
  296. package/dist/src/sources/sigv4.d.ts.map +1 -1
  297. package/dist/src/sources/sigv4.js +6 -4
  298. package/dist/src/sources/sigv4.js.map +1 -1
  299. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  300. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  301. package/dist/src/sources/sparql/descriptor.js +64 -0
  302. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  303. package/dist/src/sources/sparql/index.d.ts +28 -0
  304. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  305. package/dist/src/sources/sparql/index.js +314 -0
  306. package/dist/src/sources/sparql/index.js.map +1 -0
  307. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  308. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  309. package/dist/src/sources/sparql/ntriples.js +180 -0
  310. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  311. package/dist/src/sources/sparql/params.d.ts +27 -0
  312. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  313. package/dist/src/sources/sparql/params.js +5 -0
  314. package/dist/src/sources/sparql/params.js.map +1 -0
  315. package/dist/src/sources/sparql/query.d.ts +72 -0
  316. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  317. package/dist/src/sources/sparql/query.js +113 -0
  318. package/dist/src/sources/sparql/query.js.map +1 -0
  319. package/dist/src/sources/types.d.ts +31 -0
  320. package/dist/src/sources/types.d.ts.map +1 -1
  321. package/dist/src/styles/annotations.d.ts +61 -5
  322. package/dist/src/styles/annotations.d.ts.map +1 -1
  323. package/dist/src/styles/annotations.js +130 -22
  324. package/dist/src/styles/annotations.js.map +1 -1
  325. package/dist/src/styles/canon/bends.d.ts +46 -0
  326. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  327. package/dist/src/styles/canon/bends.js +123 -0
  328. package/dist/src/styles/canon/bends.js.map +1 -1
  329. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  330. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  331. package/dist/src/styles/canon/color-tables.js +10 -4
  332. package/dist/src/styles/canon/color-tables.js.map +1 -1
  333. package/dist/src/styles/canon/color.d.ts +3 -1
  334. package/dist/src/styles/canon/color.d.ts.map +1 -1
  335. package/dist/src/styles/canon/color.js +103 -3
  336. package/dist/src/styles/canon/color.js.map +1 -1
  337. package/dist/src/styles/canon/enums.d.ts +2 -2
  338. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  339. package/dist/src/styles/canon/enums.js +81 -7
  340. package/dist/src/styles/canon/enums.js.map +1 -1
  341. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  342. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  343. package/dist/src/styles/canon/graphviz.js +57 -9
  344. package/dist/src/styles/canon/graphviz.js.map +1 -1
  345. package/dist/src/styles/canon/number.d.ts +8 -0
  346. package/dist/src/styles/canon/number.d.ts.map +1 -1
  347. package/dist/src/styles/canon/number.js +18 -0
  348. package/dist/src/styles/canon/number.js.map +1 -1
  349. package/dist/src/styles/canon/text.d.ts +29 -2
  350. package/dist/src/styles/canon/text.d.ts.map +1 -1
  351. package/dist/src/styles/canon/text.js +156 -16
  352. package/dist/src/styles/canon/text.js.map +1 -1
  353. package/dist/src/styles/codes.d.ts +2 -0
  354. package/dist/src/styles/codes.d.ts.map +1 -1
  355. package/dist/src/styles/codes.js +2 -0
  356. package/dist/src/styles/codes.js.map +1 -1
  357. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  358. package/dist/src/styles/cyjs/cascade.js +1015 -79
  359. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  360. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  361. package/dist/src/styles/cyjs/defaults-table.js +3 -0
  362. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  363. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  364. package/dist/src/styles/cyjs/emit.js +202 -9
  365. package/dist/src/styles/cyjs/emit.js.map +1 -1
  366. package/dist/src/styles/cyjs/face.d.ts +20 -0
  367. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  368. package/dist/src/styles/cyjs/face.js +332 -0
  369. package/dist/src/styles/cyjs/face.js.map +1 -0
  370. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  371. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  372. package/dist/src/styles/cyjs/mappers.js +461 -26
  373. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  374. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  375. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  376. package/dist/src/styles/cyjs/routes.js +360 -0
  377. package/dist/src/styles/cyjs/routes.js.map +1 -0
  378. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  379. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  380. package/dist/src/styles/cytoscape/charts.js +560 -0
  381. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  382. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  383. package/dist/src/styles/cytoscape/emit.js +156 -48
  384. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  385. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  386. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  387. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  388. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  389. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  390. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  391. package/dist/src/styles/cytoscape/mappings.js +92 -0
  392. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  393. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  394. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  395. package/dist/src/styles/cytoscape/resolve.js +623 -17
  396. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  397. package/dist/src/styles/defaults.d.ts +46 -26
  398. package/dist/src/styles/defaults.d.ts.map +1 -1
  399. package/dist/src/styles/defaults.js +308 -71
  400. package/dist/src/styles/defaults.js.map +1 -1
  401. package/dist/src/styles/index.d.ts +4 -3
  402. package/dist/src/styles/index.d.ts.map +1 -1
  403. package/dist/src/styles/index.js +3 -2
  404. package/dist/src/styles/index.js.map +1 -1
  405. package/dist/src/styles/internal.d.ts +1 -0
  406. package/dist/src/styles/internal.d.ts.map +1 -1
  407. package/dist/src/styles/internal.js +1 -0
  408. package/dist/src/styles/internal.js.map +1 -1
  409. package/dist/src/styles/io/generic.d.ts.map +1 -1
  410. package/dist/src/styles/io/generic.js +56 -16
  411. package/dist/src/styles/io/generic.js.map +1 -1
  412. package/dist/src/styles/io/round-trip.d.ts +56 -0
  413. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  414. package/dist/src/styles/io/round-trip.js +138 -0
  415. package/dist/src/styles/io/round-trip.js.map +1 -0
  416. package/dist/src/styles/io/writer.d.ts.map +1 -1
  417. package/dist/src/styles/io/writer.js +6 -1
  418. package/dist/src/styles/io/writer.js.map +1 -1
  419. package/dist/src/styles/notes.d.ts.map +1 -1
  420. package/dist/src/styles/notes.js +1 -0
  421. package/dist/src/styles/notes.js.map +1 -1
  422. package/dist/src/styles/plan/features.d.ts +1 -1
  423. package/dist/src/styles/plan/features.d.ts.map +1 -1
  424. package/dist/src/styles/plan/features.js +22 -2
  425. package/dist/src/styles/plan/features.js.map +1 -1
  426. package/dist/src/styles/plan/index.d.ts +1 -1
  427. package/dist/src/styles/plan/index.d.ts.map +1 -1
  428. package/dist/src/styles/plan/index.js +1 -1
  429. package/dist/src/styles/plan/index.js.map +1 -1
  430. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  431. package/dist/src/styles/plan/plan.js +61 -4
  432. package/dist/src/styles/plan/plan.js.map +1 -1
  433. package/dist/src/styles/plan/resolve.d.ts +11 -0
  434. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  435. package/dist/src/styles/plan/resolve.js +40 -4
  436. package/dist/src/styles/plan/resolve.js.map +1 -1
  437. package/dist/src/styles/slots.d.ts +14 -0
  438. package/dist/src/styles/slots.d.ts.map +1 -0
  439. package/dist/src/styles/slots.js +20 -0
  440. package/dist/src/styles/slots.js.map +1 -0
  441. package/dist/src/styles/types.d.ts +622 -6
  442. package/dist/src/styles/types.d.ts.map +1 -1
  443. package/dist/src/styles/vocabulary.d.ts +3 -2
  444. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  445. package/dist/src/styles/vocabulary.js +203 -0
  446. package/dist/src/styles/vocabulary.js.map +1 -1
  447. package/dist/styles.js +30 -239
  448. package/dist/styles.js.map +1 -1
  449. package/dist/xgmml.js +3 -3
  450. package/package.json +27 -7
  451. package/src/formats/cx/importer.ts +6 -1
  452. package/src/formats/cx/styles.ts +143 -9
  453. package/src/formats/cx2/importer.ts +1 -0
  454. package/src/formats/cx2/styles.ts +3 -1
  455. package/src/formats/cys/importer.ts +1 -0
  456. package/src/formats/cys/styles.ts +27 -5
  457. package/src/formats/dot/drawing.ts +799 -0
  458. package/src/formats/dot/importer.ts +120 -35
  459. package/src/formats/dot/label-places.ts +228 -0
  460. package/src/formats/dot/record.ts +336 -0
  461. package/src/formats/dot/styles.ts +1654 -153
  462. package/src/formats/gexf/dialog-metrics.ts +61 -0
  463. package/src/formats/gexf/importer.ts +50 -5
  464. package/src/formats/gexf/preview.ts +217 -0
  465. package/src/formats/gexf/schema.ts +2 -1
  466. package/src/formats/gexf/styles.ts +1099 -245
  467. package/src/formats/gml/importer.ts +291 -76
  468. package/src/formats/gml/index.ts +1 -1
  469. package/src/formats/gml/positions.ts +29 -7
  470. package/src/formats/gml/styles.ts +851 -109
  471. package/src/formats/graphml/styles-plain.ts +6 -15
  472. package/src/formats/graphml/styles-yed.ts +762 -173
  473. package/src/formats/graphml/styles-yfiles3.ts +485 -63
  474. package/src/formats/graphml/yfiles.ts +19 -6
  475. package/src/formats/json/dialect.ts +41 -5
  476. package/src/formats/json/importer.ts +59 -7
  477. package/src/formats/json/index.ts +1 -0
  478. package/src/formats/json/positions.ts +22 -5
  479. package/src/formats/json/styles.ts +2041 -185
  480. package/src/formats/pajek/draw.ts +458 -0
  481. package/src/formats/pajek/exporter.ts +81 -49
  482. package/src/formats/pajek/importer.ts +278 -103
  483. package/src/formats/pajek/index.ts +1 -0
  484. package/src/formats/pajek/styles.ts +1381 -133
  485. package/src/formats/pajek/syntax.ts +27 -2
  486. package/src/formats/xgmml/emit.ts +73 -5
  487. package/src/formats/xgmml/styles.ts +330 -71
  488. package/src/index.ts +5 -1
  489. package/src/positions/convert.ts +12 -1
  490. package/src/positions/extract.ts +55 -1
  491. package/src/positions/index.ts +1 -0
  492. package/src/positions/types.ts +60 -0
  493. package/src/sources/builtins.ts +8 -1
  494. package/src/sources/context.ts +1 -0
  495. package/src/sources/cypher/descriptor.ts +7 -1
  496. package/src/sources/cypher/index.ts +148 -18
  497. package/src/sources/cypher/params.ts +1 -1
  498. package/src/sources/cypher/query-builder.ts +33 -0
  499. package/src/sources/ids.ts +6 -0
  500. package/src/sources/params.ts +3 -0
  501. package/src/sources/rest/descriptor.ts +5 -0
  502. package/src/sources/rest/source.ts +16 -0
  503. package/src/sources/sigv4.ts +6 -4
  504. package/src/sources/sparql/descriptor.ts +67 -0
  505. package/src/sources/sparql/index.ts +356 -0
  506. package/src/sources/sparql/ntriples.ts +219 -0
  507. package/src/sources/sparql/params.ts +28 -0
  508. package/src/sources/sparql/query.ts +162 -0
  509. package/src/sources/types.ts +35 -0
  510. package/src/styles/annotations.ts +201 -27
  511. package/src/styles/canon/bends.ts +137 -0
  512. package/src/styles/canon/color-tables.ts +10 -4
  513. package/src/styles/canon/color.ts +105 -3
  514. package/src/styles/canon/enums.ts +98 -8
  515. package/src/styles/canon/graphviz.ts +71 -10
  516. package/src/styles/canon/number.ts +19 -0
  517. package/src/styles/canon/text.ts +187 -16
  518. package/src/styles/codes.ts +2 -0
  519. package/src/styles/cyjs/cascade.ts +1160 -84
  520. package/src/styles/cyjs/defaults-table.ts +3 -0
  521. package/src/styles/cyjs/emit.ts +233 -13
  522. package/src/styles/cyjs/face.ts +372 -0
  523. package/src/styles/cyjs/mappers.ts +492 -27
  524. package/src/styles/cyjs/routes.ts +432 -0
  525. package/src/styles/cytoscape/charts.ts +684 -0
  526. package/src/styles/cytoscape/emit.ts +170 -48
  527. package/src/styles/cytoscape/lexicon.ts +431 -78
  528. package/src/styles/cytoscape/mappings.ts +108 -0
  529. package/src/styles/cytoscape/resolve.ts +741 -17
  530. package/src/styles/defaults.ts +417 -108
  531. package/src/styles/index.ts +5 -0
  532. package/src/styles/internal.ts +1 -0
  533. package/src/styles/io/generic.ts +79 -23
  534. package/src/styles/io/round-trip.ts +202 -0
  535. package/src/styles/io/writer.ts +6 -1
  536. package/src/styles/notes.ts +1 -0
  537. package/src/styles/plan/features.ts +23 -2
  538. package/src/styles/plan/index.ts +1 -1
  539. package/src/styles/plan/plan.ts +69 -5
  540. package/src/styles/plan/resolve.ts +47 -4
  541. package/src/styles/slots.ts +25 -0
  542. package/src/styles/types.ts +633 -5
  543. package/src/styles/vocabulary.ts +211 -2
  544. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  545. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  546. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  547. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  548. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  549. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  550. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  551. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  552. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  553. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  554. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  555. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  556. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  557. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  558. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  559. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  560. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  561. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  562. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  563. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  564. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  565. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  566. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  567. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  568. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  569. package/dist/chunks/writer-DvHTl36J.js +0 -449
  570. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -33,12 +33,21 @@ export interface AnnotationBase {
33
33
  readonly z: number;
34
34
  }
35
35
 
36
+ /**
37
+ * How far an annotation is turned about its box's center, in degrees, clockwise as seen on screen (0: not turned).
38
+ * Shapes, texts and pictures carry it; Cytoscape saves it as `rotation`.
39
+ */
40
+ interface RotatedAnnotation {
41
+ /** The turn in degrees, clockwise on screen. */
42
+ readonly rotation: number;
43
+ }
44
+
36
45
  /**
37
46
  * A filled, outlined shape.
38
47
  * @category Styles
39
48
  */
40
- export interface ShapeAnnotation extends AnnotationBase {
41
- /** Which kind of annotation this is: always "shape". */
49
+ export interface ShapeAnnotation extends AnnotationBase, RotatedAnnotation {
50
+ /** What the annotation is: always `"shape"` for a shape. */
42
51
  readonly kind: "shape";
43
52
  /** The box's center. */
44
53
  readonly center: AnnotationPoint;
@@ -64,8 +73,8 @@ export interface ShapeAnnotation extends AnnotationBase {
64
73
  * A line of text.
65
74
  * @category Styles
66
75
  */
67
- export interface TextAnnotation extends AnnotationBase {
68
- /** Which kind of annotation this is: always "text". */
76
+ export interface TextAnnotation extends AnnotationBase, RotatedAnnotation {
77
+ /** What the annotation is: always `"text"` for a line of text. */
69
78
  readonly kind: "text";
70
79
  /** The text. */
71
80
  readonly text: string;
@@ -92,7 +101,7 @@ export interface TextAnnotation extends AnnotationBase {
92
101
  * @category Styles
93
102
  */
94
103
  export interface ArrowAnnotation extends AnnotationBase {
95
- /** Which kind of annotation this is: always "arrow". */
104
+ /** What the annotation is: always `"arrow"` for an arrow. */
96
105
  readonly kind: "arrow";
97
106
  /** Where the line starts. */
98
107
  readonly from: AnnotationPoint;
@@ -112,6 +121,46 @@ export interface ArrowAnnotation extends AnnotationBase {
112
121
  readonly sourceSize: number;
113
122
  /** The end's arrowhead size as a factor of the normal size. */
114
123
  readonly targetSize: number;
124
+ /** The arrowhead color at the start. */
125
+ readonly sourceColor: StyleColor;
126
+ /** The arrowhead color at the end. */
127
+ readonly targetColor: StyleColor;
128
+ /**
129
+ * How long the start's arrowhead is along the line, in the units of the points, size included; absent, the
130
+ * drawing program's own length for the line's width.
131
+ */
132
+ readonly sourceHeadLength?: number;
133
+ /** How wide the start's arrowhead is across the line, as `sourceHeadLength` says. */
134
+ readonly sourceHeadWidth?: number;
135
+ /** How long the end's arrowhead is along the line, as `sourceHeadLength` says. */
136
+ readonly targetHeadLength?: number;
137
+ /** How wide the end's arrowhead is across the line, as `sourceHeadLength` says. */
138
+ readonly targetHeadWidth?: number;
139
+ }
140
+
141
+ /**
142
+ * A picture placed in a box, which `readImageAnnotations()` reads.
143
+ * @category Styles
144
+ */
145
+ export interface ImageAnnotation extends AnnotationBase, RotatedAnnotation {
146
+ /** What the annotation is: always `"image"` for a picture. */
147
+ readonly kind: "image";
148
+ /** The box's center. */
149
+ readonly center: AnnotationPoint;
150
+ /** The box's width; the picture is stretched to it. */
151
+ readonly width: number;
152
+ /** The box's height. */
153
+ readonly height: number;
154
+ /** Where the picture is, as the file names it. */
155
+ readonly url: string;
156
+ /** The picture's opacity, 0..1. */
157
+ readonly opacity: number;
158
+ /** The outline's color. */
159
+ readonly borderColor: StyleColor;
160
+ /** The outline's opacity, 0..1 (0 draws none). */
161
+ readonly borderOpacity: number;
162
+ /** The outline's width (0 draws none). */
163
+ readonly borderWidth: number;
115
164
  }
116
165
 
117
166
  /**
@@ -151,11 +200,13 @@ const SHAPES: ReadonlyMap<string, StyleNodeShape> = new Map<string, StyleNodeSha
151
200
  ["parallelogram", "parallelogram"],
152
201
  ["star5", "star"],
153
202
  ["star6", "star"],
203
+ ["v", "vee"],
154
204
  ]);
155
205
 
156
206
  /**
157
- * Cytoscape's annotation arrowheads, by the position in its `ArrowType` list (older sessions) and by name (newer
158
- * ones), lowercase.
207
+ * Cytoscape's annotation arrowheads, by the number it saves (the declaration order of ding's
208
+ * `ArrowAnnotationImpl.ArrowType` in 3.10: Circle, Closed Arrow, Concave Arrow, Diamond, Open Arrow, No Arrow,
209
+ * X Arrow, Triangular Head, T-Shape) and by its display name, lowercase.
159
210
  */
160
211
  const ARROW_ORDER: readonly StyleArrowShape[] = [
161
212
  "circle",
@@ -164,13 +215,18 @@ const ARROW_ORDER: readonly StyleArrowShape[] = [
164
215
  "diamond",
165
216
  "triangle-open",
166
217
  "none",
167
- "tee",
168
- "triangle",
169
- "triangle",
218
+ "other:x",
170
219
  "triangle",
171
220
  "tee",
172
- "other:x",
173
221
  ];
222
+ /**
223
+ * How long along its line each of Cytoscape's annotation arrowheads is drawn at size 1, by its `ArrowType` position,
224
+ * every one 10 wide whatever the line's width (measured on Cytoscape 3.10.5's SVG of `specimen-images-charts-p6`):
225
+ * the Closed, Concave, Diamond and Open Arrows 17, the Circle and the X 10, the Triangular Head 5, the T a bar across.
226
+ */
227
+ const ARROW_LENGTHS: readonly number[] = [10, 17, 17, 17, 17, 0, 10, 5, 0];
228
+ /** How wide across its line every Cytoscape annotation arrowhead is at size 1. */
229
+ const ARROW_WIDTH = 10;
174
230
  const ARROW_NAMES: ReadonlyMap<string, StyleArrowShape> = new Map<string, StyleArrowShape>([
175
231
  ["circle", "circle"],
176
232
  ["closed arrow", "triangle"],
@@ -181,7 +237,10 @@ const ARROW_NAMES: ReadonlyMap<string, StyleArrowShape> = new Map<string, StyleA
181
237
  ["pipe", "tee"],
182
238
  ["triangle", "triangle"],
183
239
  ["t", "tee"],
240
+ ["t-shape", "tee"],
241
+ ["triangular head", "triangle"],
184
242
  ["x", "other:x"],
243
+ ["x arrow", "other:x"],
185
244
  ]);
186
245
 
187
246
  /**
@@ -209,6 +268,49 @@ export function readAnnotations(snapshot: GraphSnapshot): FileAnnotations {
209
268
  return { annotations, skipped: [...skipped] };
210
269
  }
211
270
 
271
+ /**
272
+ * The pictures a graph's annotations place, from the column Cytoscape desktop keeps them in: the annotations
273
+ * `readAnnotations()` lists as skipped `ImageAnnotation`s.
274
+ * @param snapshot - the graph
275
+ * @returns the pictures, in the file's order; none when the graph has none
276
+ * @category Styles
277
+ */
278
+ export function readImageAnnotations(snapshot: GraphSnapshot): ImageAnnotation[] {
279
+ const { graph } = snapshot;
280
+ const cell = graph.has(CYTOSCAPE_ANNOTATIONS_COLUMN) ? graph.value(CYTOSCAPE_ANNOTATIONS_COLUMN, 0) : null;
281
+ return cellStrings(cell).flatMap((entry, i) => {
282
+ const f = parseEntry(entry);
283
+ const url = f.get("URL") ?? "";
284
+ if ((f.get("type") ?? "").replace(TYPE_PREFIX, "") !== "ImageAnnotation" || url === "") {
285
+ return [];
286
+ }
287
+ const zoom = positive(f.get("zoom")) ?? 1;
288
+ const x = num(f.get("x")) ?? 0;
289
+ const y = num(f.get("y")) ?? 0;
290
+ const width = (positive(f.get("width")) ?? 0) / zoom;
291
+ const height = (positive(f.get("height")) ?? 0) / zoom;
292
+ const border = javaColor(f.get("edgeColor")) ?? { color: "#000000", alpha: 1 };
293
+ const opacity = num(f.get("opacity"));
294
+ return [
295
+ {
296
+ id: f.get("uuid") ?? String(i),
297
+ layer: f.get("canvas") === "background" ? "background" : "foreground",
298
+ z: num(f.get("z")) ?? 0,
299
+ kind: "image",
300
+ rotation: num(f.get("rotation")) ?? 0,
301
+ center: { x: x + width / 2, y: -(y + height / 2) },
302
+ width,
303
+ height,
304
+ url,
305
+ opacity: opacity === null ? 1 : Math.min(1, Math.max(0, opacity)),
306
+ borderColor: border.color,
307
+ borderOpacity: border.alpha * percent(f.get("edgeOpacity")),
308
+ borderWidth: (num(f.get("edgeThickness")) ?? 0) / zoom,
309
+ },
310
+ ];
311
+ });
312
+ }
313
+
212
314
  /**
213
315
  * A cell's strings: a list cell's items, or the lines of a text cell.
214
316
  * @param cell - the cell
@@ -292,6 +394,7 @@ function shapeOf(f: ReadonlyMap<string, string>, base: AnnotationBase, zoom: num
292
394
  return {
293
395
  ...base,
294
396
  kind: "shape",
397
+ rotation: num(f.get("rotation")) ?? 0,
295
398
  center: { x: x + width / 2, y: -(y + height / 2) },
296
399
  width,
297
400
  height,
@@ -326,6 +429,7 @@ function textOf(
326
429
  return {
327
430
  ...base,
328
431
  kind: "text",
432
+ rotation: num(f.get("rotation")) ?? 0,
329
433
  text: f.get("text") ?? "",
330
434
  at,
331
435
  anchor,
@@ -340,9 +444,11 @@ function textOf(
340
444
 
341
445
  /**
342
446
  * An arrow annotation. Cytoscape keeps its start as the annotation it leaves (`sourceAnnotation`) and its end as a
343
- * point, a node's center at save time (`targetNode`) or another annotation, and saves the arrow's top-left corner
344
- * as `x`, `y`: the start wherever the end lies right of and below it, which is taken for the start, else the center
345
- * of the annotation it leaves.
447
+ * point (`targetPoint`), a node's center at save time (`targetNode`) or another annotation (`targetAnnotation`). It
448
+ * draws the line from the middle of the side of the source annotation's box that faces the end, to the end point or
449
+ * the middle of the facing side of the target annotation's box, at half the saved `lineThickness` and never under
450
+ * 1 (measured on Cytoscape 3.10.5's SVG of `specimen-images-charts-p6` and of the tutorial session). A source with
451
+ * no saved size (a text annotation) leaves from the arrow's saved `x`, `y` corner.
346
452
  * @param f - its fields
347
453
  * @param base - its id, layer and order
348
454
  * @param zoom - the zoom its line width was saved at
@@ -355,17 +461,26 @@ function arrowOf(
355
461
  zoom: number,
356
462
  byId: ReadonlyMap<string, ReadonlyMap<string, string>>,
357
463
  ): ArrowAnnotation[] | null {
358
- const target = f.get("targetAnnotation");
359
- const to = point(f.get("targetPoint")) ?? point(f.get("targetNode")) ?? centerOf(byId.get(target ?? ""), zoom);
360
- if (to === null) {
464
+ const sourceBox = boxOf(byId.get(f.get("sourceAnnotation") ?? ""), zoom);
465
+ const targetBox = boxOf(byId.get(f.get("targetAnnotation") ?? ""), zoom);
466
+ const toPoint = point(f.get("targetPoint")) ?? point(f.get("targetNode"));
467
+ const corner = { x: num(f.get("x")) ?? 0, y: num(f.get("y")) ?? 0 };
468
+ const sourceCenter = sourceBox === null ? corner : centerOfBox(sourceBox);
469
+ const aim = toPoint ?? (targetBox === null ? null : centerOfBox(targetBox));
470
+ if (aim === null) {
361
471
  return null;
362
472
  }
363
- const corner = { x: num(f.get("x")) ?? 0, y: num(f.get("y")) ?? 0 };
364
- const source = centerOf(byId.get(f.get("sourceAnnotation") ?? ""), zoom) ?? corner;
365
- // ponytail: the start is exact only when the end lies right of and below it; elsewhere the center of the
366
- // annotation it leaves, as Cytoscape stores no other start. Clip to that annotation's box if it matters.
367
- const from = { x: to.x > corner.x ? corner.x : source.x, y: to.y > corner.y ? corner.y : source.y };
473
+ // a source with no saved size (a text) leaves from the arrow's saved top-left corner where the end lies right of
474
+ // and below it, else from the source's corner: the file keeps no other trace of where the text was drawn
475
+ const from =
476
+ sourceBox !== null && sourceBox.width > 0 && sourceBox.height > 0
477
+ ? facing(sourceBox, aim)
478
+ : { x: aim.x > corner.x ? corner.x : sourceCenter.x, y: aim.y > corner.y ? corner.y : sourceCenter.y };
479
+ // ponytail: a node end stops at its center; Cytoscape stops at the node's box, which needs the node's size
480
+ const to = toPoint ?? facing(targetBox ?? { x: aim.x, y: aim.y, width: 0, height: 0 }, sourceCenter);
368
481
  const color = javaColor(f.get("lineColor")) ?? { color: "#000000", alpha: 1 };
482
+ const sourceColor = javaColor(f.get("sourceColor"))?.color ?? color.color;
483
+ const targetColor = javaColor(f.get("targetColor"))?.color ?? color.color;
369
484
  return [
370
485
  {
371
486
  ...base,
@@ -374,22 +489,55 @@ function arrowOf(
374
489
  to: { x: to.x, y: -to.y },
375
490
  color: color.color,
376
491
  opacity: color.alpha * percent(f.get("lineOpacity")),
377
- width: (positive(f.get("lineThickness")) ?? 1) / zoom,
492
+ width: Math.max(1, (positive(f.get("lineThickness")) ?? 1) / zoom / 2),
378
493
  sourceArrow: arrowShape(f.get("sourceType")),
379
494
  targetArrow: arrowShape(f.get("targetType")),
380
495
  sourceSize: positive(f.get("sourceSize")) ?? 1,
381
496
  targetSize: positive(f.get("targetSize")) ?? 1,
497
+ sourceColor,
498
+ targetColor,
499
+ ...heads("source", f.get("sourceType"), positive(f.get("sourceSize")) ?? 1),
500
+ ...heads("target", f.get("targetType"), positive(f.get("targetSize")) ?? 1),
382
501
  },
383
502
  ];
384
503
  }
385
504
 
386
505
  /**
387
- * An annotation's center, y down as the file writes it: a shape's box center, a text's corner.
506
+ * The length and width Cytoscape draws one end's arrowhead at: its type's length and 10 across, times its size.
507
+ * @param end - which end
508
+ * @param type - the end's saved `ArrowType`, a position or a name
509
+ * @param size - the end's saved size
510
+ * @returns the end's head length and width, none for an end without a head
511
+ */
512
+ function heads(
513
+ end: "source" | "target",
514
+ type: string | undefined,
515
+ size: number,
516
+ ): Partial<Pick<ArrowAnnotation, "sourceHeadLength" | "sourceHeadWidth" | "targetHeadLength" | "targetHeadWidth">> {
517
+ const shape = arrowShape(type);
518
+ if (shape === "none") {
519
+ return {};
520
+ }
521
+ const k = num(type) ?? ARROW_ORDER.indexOf(shape);
522
+ const length = ARROW_LENGTHS[k] ?? ARROW_LENGTHS[1];
523
+ return { [`${end}HeadLength`]: length * size, [`${end}HeadWidth`]: ARROW_WIDTH * size };
524
+ }
525
+
526
+ /** An annotation's box as the file writes it: top-left corner, y down. */
527
+ interface FileBox {
528
+ readonly x: number;
529
+ readonly y: number;
530
+ readonly width: number;
531
+ readonly height: number;
532
+ }
533
+
534
+ /**
535
+ * An annotation's box, y down as the file writes it.
388
536
  * @param f - its fields, or undefined
389
537
  * @param zoom - the zoom the arrow was saved at
390
- * @returns the point, or null
538
+ * @returns the box, or null
391
539
  */
392
- function centerOf(f: ReadonlyMap<string, string> | undefined, zoom: number): AnnotationPoint | null {
540
+ function boxOf(f: ReadonlyMap<string, string> | undefined, zoom: number): FileBox | null {
393
541
  if (f === undefined) {
394
542
  return null;
395
543
  }
@@ -398,7 +546,33 @@ function centerOf(f: ReadonlyMap<string, string> | undefined, zoom: number): Ann
398
546
  if (x === null || y === null) {
399
547
  return null;
400
548
  }
401
- return { x: x + (positive(f.get("width")) ?? 0) / zoom / 2, y: y + (positive(f.get("height")) ?? 0) / zoom / 2 };
549
+ return { x, y, width: (positive(f.get("width")) ?? 0) / zoom, height: (positive(f.get("height")) ?? 0) / zoom };
550
+ }
551
+
552
+ /**
553
+ * A box's center.
554
+ * @param b - the box
555
+ * @returns the center
556
+ */
557
+ function centerOfBox(b: FileBox): AnnotationPoint {
558
+ return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
559
+ }
560
+
561
+ /**
562
+ * The middle of the side of a box that faces a point: a left or right side when the point lies more across than
563
+ * along, against the box's own proportions, else the top or bottom.
564
+ * @param b - the box
565
+ * @param p - the point
566
+ * @returns the side's middle
567
+ */
568
+ function facing(b: FileBox, p: AnnotationPoint): AnnotationPoint {
569
+ const c = centerOfBox(b);
570
+ const dx = p.x - c.x;
571
+ const dy = p.y - c.y;
572
+ if (Math.abs(dx) * b.height >= Math.abs(dy) * b.width) {
573
+ return { x: c.x + Math.sign(dx) * (b.width / 2), y: c.y };
574
+ }
575
+ return { x: c.x, y: c.y + Math.sign(dy) * (b.height / 2) };
402
576
  }
403
577
 
404
578
  /**
@@ -82,3 +82,140 @@ export function bendsToPoints(source: BendPoint, target: BendPoint, value: strin
82
82
  }
83
83
  return out.length === 0 ? null : out;
84
84
  }
85
+
86
+ /**
87
+ * The points a piecewise cubic Bezier curve passes through, sampled evenly in its parameter: the first control point,
88
+ * then `steps` points along each segment, its last control point included. The input is `3n + 1` control points
89
+ * (a Graphviz spline, a cubic path), each segment sharing its first point with the one before.
90
+ * @param controls - the control points
91
+ * @param steps - how many points each segment is sampled at
92
+ * @returns the points, or null when the count is not `3n + 1` for some n >= 1
93
+ * @category Styles
94
+ */
95
+ export function flattenCubic(controls: readonly BendPoint[], steps = 8): BendPoint[] | null {
96
+ if (controls.length < 4 || (controls.length - 1) % 3 !== 0) {
97
+ return null;
98
+ }
99
+ const out: BendPoint[] = [controls[0]];
100
+ for (let s = 0; s + 3 < controls.length; s += 3) {
101
+ const [p0, p1, p2, p3] = controls.slice(s, s + 4);
102
+ for (let k = 1; k <= steps; k++) {
103
+ const t = k / steps;
104
+ const u = 1 - t;
105
+ const w = [u * u * u, 3 * u * u * t, 3 * u * t * t, t * t * t];
106
+ out.push([
107
+ w[0] * p0[0] + w[1] * p1[0] + w[2] * p2[0] + w[3] * p3[0],
108
+ w[0] * p0[1] + w[1] * p1[1] + w[2] * p2[1] + w[3] * p3[1],
109
+ ]);
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+
115
+ /**
116
+ * Points placed on and around one node, each relative to its center as fractions of its half width and half height,
117
+ * y up: `"1,0"` is the middle of its right side, `"0,1"` the middle of its top. The value of an edge end's port
118
+ * (`sourcePort`, `targetPort`) and of a self-loop's `bends`, which have no line between two centers to be relative
119
+ * to. Relative to the node's size, so a drawing that draws the node larger keeps the point on the same spot.
120
+ * @param center - the node's center
121
+ * @param size - its width and height
122
+ * @param points - the points
123
+ * @param yDown - true when the file's y axis points down (the value is always y up)
124
+ * @returns the value, or null with no points, a size that is not positive, or a coordinate that is not finite
125
+ * @category Styles
126
+ */
127
+ export function canonNodeOffsets(
128
+ center: BendPoint,
129
+ size: BendPoint,
130
+ points: readonly BendPoint[],
131
+ yDown: boolean,
132
+ ): string | null {
133
+ const [hw, hh] = [size[0] / 2, size[1] / 2];
134
+ if (points.length === 0 || Number.isNaN(hw + hh) || hw <= 0 || hh <= 0) {
135
+ return null;
136
+ }
137
+ const flip = yDown ? -1 : 1;
138
+ const out: string[] = [];
139
+ for (const [px, py] of points) {
140
+ const x = (px - center[0]) / hw;
141
+ const y = ((py - center[1]) * flip) / hh;
142
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
143
+ return null;
144
+ }
145
+ out.push(`${fraction(x)},${fraction(y)}`);
146
+ }
147
+ return out.join(" ");
148
+ }
149
+
150
+ /**
151
+ * The points a node-relative value places around a node: the inverse of {@link canonNodeOffsets}.
152
+ * @param center - the node's center
153
+ * @param size - its width and height
154
+ * @param value - the value
155
+ * @param yDown - true when the points are wanted in a y-down file's coordinates
156
+ * @returns the points, or null when the value is not `x,y` pairs or a coordinate is not finite
157
+ * @category Styles
158
+ */
159
+ export function nodeOffsetsToPoints(
160
+ center: BendPoint,
161
+ size: BendPoint,
162
+ value: string,
163
+ yDown: boolean,
164
+ ): BendPoint[] | null {
165
+ const flip = yDown ? -1 : 1;
166
+ const out: BendPoint[] = [];
167
+ for (const pair of value.trim().split(/\s+/)) {
168
+ const [a, b, extra] = pair.split(",").map(Number);
169
+ const x = center[0] + (a * size[0]) / 2;
170
+ const y = center[1] + (b * size[1] * flip) / 2;
171
+ if (extra !== undefined || !Number.isFinite(x) || !Number.isFinite(y)) {
172
+ return null;
173
+ }
174
+ out.push([x, y]);
175
+ }
176
+ return out.length === 0 ? null : out;
177
+ }
178
+
179
+ /**
180
+ * The points a quadratic spline passes through, as yEd draws a quad curve edge: its first and last control points are
181
+ * the ends, every control point between them pulls the curve without lying on it, and the curve runs from the middle
182
+ * of the leg before such a point to the middle of the leg after it (from the end itself on the first and last legs).
183
+ * `straightness` (0..1) keeps that share of every leg straight, so each curved piece covers only the part of its two
184
+ * legs nearest its control point: 0 is the smooth spline, 1 the control polygon.
185
+ * @param controls - the control points, ends included
186
+ * @param straightness - how straight the legs stay, 0..1
187
+ * @param steps - how many points each curved piece is sampled at
188
+ * @returns the points, ends included; the controls themselves with fewer than three
189
+ * @category Styles
190
+ */
191
+ export function flattenQuadSpline(controls: readonly BendPoint[], straightness: number, steps = 8): BendPoint[] {
192
+ if (controls.length < 3) {
193
+ return [...controls];
194
+ }
195
+ const s = Math.min(1, Math.max(0, Number.isFinite(straightness) ? straightness : 0));
196
+ const lerp = (a: BendPoint, b: BendPoint, t: number): BendPoint => [
197
+ a[0] + (b[0] - a[0]) * t,
198
+ a[1] + (b[1] - a[1]) * t,
199
+ ];
200
+ const last = controls.length - 1;
201
+ const out: BendPoint[] = [controls[0]];
202
+ for (let i = 1; i < last; i++) {
203
+ const c = controls[i];
204
+ // the joins either side: the middle of each leg, or the end itself on the first and last
205
+ const before = i === 1 ? controls[0] : lerp(controls[i - 1], c, 0.5);
206
+ const after = i === last - 1 ? controls[last] : lerp(c, controls[i + 1], 0.5);
207
+ const from = lerp(c, before, 1 - s);
208
+ const to = lerp(c, after, 1 - s);
209
+ for (let k = 0; k <= steps; k++) {
210
+ const t = k / steps;
211
+ const u = 1 - t;
212
+ out.push([
213
+ u * u * from[0] + 2 * u * t * c[0] + t * t * to[0],
214
+ u * u * from[1] + 2 * u * t * c[1] + t * t * to[1],
215
+ ]);
216
+ }
217
+ }
218
+ out.push(controls[last]);
219
+ // a piece that starts where the one before ends (straightness 0) repeats the join
220
+ return out.filter((p, k) => k === 0 || p[0] !== out[k - 1][0] || p[1] !== out[k - 1][1]);
221
+ }
@@ -169,11 +169,19 @@ export const X11_COLORS: ReadonlyMap<string, string> = table(
169
169
  "tomato3=cd4f39 tomato4=8b3626 turquoise=40e0d0 turquoise1=00f5ff turquoise2=00e5ee turquoise3=00c5cd " +
170
170
  "turquoise4=00868b violet=ee82ee violetred=d02090 violetred1=ff3e96 violetred2=ee3a8c violetred3=cd3278 " +
171
171
  "violetred4=8b2252 wheat=f5deb3 wheat1=ffe7ba wheat2=eed8ae wheat3=cdba96 wheat4=8b7e66 white=ffffff " +
172
+ // added in later Graphviz releases (measured on 14.1.2): the web and X11 spellings of the five clashing names
173
+ "webgray=808080 webgreen=008000 webgrey=808080 webmaroon=800000 webpurple=800080 x11gray=bebebe " +
174
+ "x11green=00ff00 x11grey=bebebe x11maroon=b03060 x11purple=a020f0 " +
172
175
  "whitesmoke=f5f5f5 yellow=ffff00 yellow1=ffff00 yellow2=eeee00 yellow3=cdcd00 yellow4=8b8b00 " +
173
176
  "yellowgreen=9acd32",
174
177
  );
175
178
 
176
- /** dvips names, case as Pajek spells them. */
179
+ /**
180
+ * dvips names, case as Pajek spells them, and the ten Pajek adds (from LightYellow on: Pajek 6.02 manual, figure 19,
181
+ * with the CMYK values of the color dictionary in Pajek's own EPS export). LightOrange is the one its SVG export draws
182
+ * otherwise: #ffd9bc, Pajek's default vertex fill, not the EPS dictionary's #ffccb3 (`pajek-specimen-node-fills-borders-p2`
183
+ * `ic-lightorange`, `pajek-graphstream-b`: 18 vertices).
184
+ */
177
185
  export const DVIPS_COLORS: ReadonlyMap<string, string> = table(
178
186
  "GreenYellow=d9ff4f Yellow=ffff00 Goldenrod=ffe629 Dandelion=ffb529 Apricot=ffad7a Peach=ff804d " +
179
187
  "Melon=ff8a80 YellowOrange=ff9400 Orange=ff6321 BurntOrange=ff7d00 Bittersweet=c20300 RedOrange=ff3b21 " +
@@ -187,10 +195,8 @@ export const DVIPS_COLORS: ReadonlyMap<string, string> = table(
187
195
  "JungleGreen=03ff7a SeaGreen=4fff80 Green=00ff00 ForestGreen=00e000 PineGreen=00bf29 LimeGreen=80ff00 " +
188
196
  "YellowGreen=8fff42 SpringGreen=bdff3d OliveGreen=009900 RawSienna=8c0000 Sepia=4d0000 Brown=660000 " +
189
197
  "Tan=db9470 Gray=808080 Black=000000 White=ffffff " +
190
- // Pajek's own names, not in dvips: the RGB fill of each swatch in the Pajek 6.02 manual, Figure 19, p. 105
191
- // (http://mrvar.fdv.uni-lj.si/pajek/pajekman.pdf); Pajek's SVG export draws LightCyan as rgb(204,255,255) too.
192
198
  "LightYellow=ffff99 LightCyan=ccffff LightMagenta=ffccff LightPurple=ccccff LightGreen=ccffb3 " +
193
- "LightOrange=ffccb3 Canary=ffff7f LFadedGreen=e6ffcc Pink=ffd9f3 LSkyBlue=d9f3ff",
199
+ "LightOrange=ffd9bc Canary=ffff80 LFadedGreen=e6ffcc Pink=ffd9f2 LSkyBlue=d9f2ff",
194
200
  );
195
201
 
196
202
  /** Java's `java.awt.Color` constants, lowercase, with and without the underscore. */
@@ -405,6 +405,76 @@ function cssColor(text: string): { hex: StyleColor; alpha: number } | null {
405
405
  return hexColor(text, false) ?? cssFunction(text);
406
406
  }
407
407
 
408
+ /**
409
+ * sigma.js's `rgb()` / `rgba()` reader (sigma/utils parseColor, the regex
410
+ * `^\s*rgba?\s*\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)(?:\s*,\s*(.*)?)?\)\s*$`), read without backtracking: integer
411
+ * channels, no space before the `)` unless an alpha follows, the alpha on one line.
412
+ * @param text - the value
413
+ * @returns the three channels' digits and the alpha's text (empty when none), or null
414
+ */
415
+ function sigmaRgba(text: string): [string, string, string, string] | null {
416
+ const t = text.trim();
417
+ const head = /^rgba?\s*\(/.exec(t);
418
+ if (head === null || !t.endsWith(")")) {
419
+ return null;
420
+ }
421
+ const parts = t.slice(head[0].length, -1).split(",");
422
+ if (parts.length < 3) {
423
+ return null;
424
+ }
425
+ const alpha = parts.slice(3).join(",").trimStart();
426
+ // the third channel runs up to the `)` when no alpha follows it
427
+ const third = parts.length > 3 ? parts[2].trim() : parts[2].trimStart();
428
+ const channels = [parts[0].trim(), parts[1].trim(), third];
429
+ if (!channels.every((c) => /^\d*$/.test(c)) || /[\n\r\u2028\u2029]/.test(alpha)) {
430
+ return null;
431
+ }
432
+ return [channels[0], channels[1], channels[2], alpha];
433
+ }
434
+
435
+ /**
436
+ * A color as sigma.js 4.0.1 reads it (sigma/utils parseColor), untrimmed: `transparent`, the 148 HTML color names in
437
+ * any case, `#rgb`, `#rrggbb` and `#rrggbbaa` (any other length is read two digits a channel, so `#f80c` is
438
+ * `#f80c00`), and `rgb()` / `rgba()` with integer channels. Anything else, the empty string included, is black.
439
+ * @param text - the value as the file has it
440
+ * @returns the color and its alpha, and whether sigma read it as a color (else it is black, or garbled)
441
+ */
442
+ function sigmaColor(text: string): { color: StyleColor; alpha: number; read: boolean } {
443
+ const lower = text.toLowerCase();
444
+ if (lower === "transparent") {
445
+ return { color: "#000000", alpha: 0, read: true };
446
+ }
447
+ const named = CSS_COLORS.get(lower);
448
+ if (named !== undefined) {
449
+ return sigmaColor(named);
450
+ }
451
+ let rgb = [0, 0, 0];
452
+ let a = 1;
453
+ let read = false;
454
+ if (text.startsWith("#")) {
455
+ read = /^#(?:[\da-f]{3}|[\da-f]{6}|[\da-f]{8})$/i.test(text);
456
+ const at = text.length === 4 ? [1, 1, 2, 2, 3, 3] : [1, 2, 3, 4, 5, 6];
457
+ // parseInt reads a leading run of hex digits; NaN (no digit) is stored as 0
458
+ rgb = [0, 2, 4].map((k) => Number.parseInt(text.charAt(at[k]) + text.charAt(at[k + 1]), 16) || 0);
459
+ if (text.length === 9) {
460
+ a = Number.parseInt(text.slice(7, 9), 16) / 255;
461
+ }
462
+ } else {
463
+ const m = sigmaRgba(text);
464
+ if (m !== null) {
465
+ read = true;
466
+ rgb = [Number(m[0]), Number(m[1]), Number(m[2])];
467
+ if (m[3]) {
468
+ a = Number(m[3]);
469
+ }
470
+ }
471
+ }
472
+ // sigma packs each channel into a byte (ponytail: a channel over 255 wraps here; sigma lets it spill into the
473
+ // next channel)
474
+ const [r, g, b] = rgb.map((v) => v & 255);
475
+ return { color: rgbHex(r, g, b), alpha: ((a * 255) & 255) / 255, read };
476
+ }
477
+
408
478
  /** One of Pajek's decimal color channels in `RGB(1,0.8,0)`: 0..1, no spaces (Pajek 6.02 manual p. 76). */
409
479
  const PAJEK_CHANNEL = /^(?:\d+(?:\.\d*)?|\.\d+)$/;
410
480
 
@@ -478,9 +548,11 @@ function channels(raw: object): { hex: StyleColor; alpha: number } | null {
478
548
  /**
479
549
  * A canonical color in the file's dialect, or null with a note.
480
550
  *
481
- * - CSS (`css`, `vis`, `graphology`, `cytoscape-js`, `graphty` and any dialect not listed): `#rgb`, `#rgba`,
551
+ * - CSS (`css`, `vis`, `cytoscape-js`, `graphty` and any dialect not listed): `#rgb`, `#rgba`,
482
552
  * `#rrggbb`, `#rrggbbaa`, `rgb()`, `rgba()`, `hsl()`, `hsla()`, CSS names and `transparent`, resolved as
483
553
  * graphty-element resolves them (out-of-range channels are gamut mapped).
554
+ * - `graphology`: sigma.js's own parser (see `sigmaColor`); a string it cannot read is BLACK, with a note, because
555
+ * that is what sigma draws, and a value that is not a string is null (sigma throws on it).
484
556
  * - `graphviz`: Graphviz's own rules (see `graphvizColor`); an unknown color is BLACK, with a note, because that is
485
557
  * what Graphviz draws. `x11`: the same names, and an unknown one is null.
486
558
  * - `java`, `gephi`, `cytoscape`: the `java.awt.Color` names first, then CSS; a `java` integer is an RGB value.
@@ -511,6 +583,12 @@ export function canonColor(
511
583
  const v = raw >>> 0;
512
584
  return { color: rgbHex((v >>> 16) & 255, (v >>> 8) & 255, v & 255), alpha: 1 };
513
585
  }
586
+ if (dialect === "graphology" && typeof raw === "string" && raw.trim() === "") {
587
+ // sigma draws a blank color black, where every other reader has no color
588
+ spendAt(site, 1);
589
+ noteAt(site, STYLE_ISSUE.BAD_VALUE, raw);
590
+ return { color: "#000000", alpha: 1 };
591
+ }
514
592
  const text = scalarText(raw, site);
515
593
  if (text === null) {
516
594
  return null;
@@ -518,6 +596,9 @@ export function canonColor(
518
596
  if (dialect === "graphviz" || dialect === "x11") {
519
597
  return graphvizCanon(text, dialect === "x11" ? "x11" : "graphviz", site, options);
520
598
  }
599
+ if (dialect === "graphology") {
600
+ return graphologyColor(raw, text, site);
601
+ }
521
602
  const c = textColor(text.trim(), dialect);
522
603
  if (c === null) {
523
604
  noteAt(site, STYLE_ISSUE.BAD_VALUE, text);
@@ -526,6 +607,26 @@ export function canonColor(
526
607
  return { color: c.hex, alpha: c.alpha };
527
608
  }
528
609
 
610
+ /**
611
+ * A graphology color as sigma.js draws it; a value that is not a string is no color, as sigma throws drawing it.
612
+ * @param raw - the file's value
613
+ * @param text - the value as text
614
+ * @param site - where it was read
615
+ * @returns the color and its alpha, or null
616
+ */
617
+ function graphologyColor(raw: unknown, text: string, site: CanonSite): CanonColor | null {
618
+ if (typeof raw !== "string") {
619
+ // sigma throws while drawing a color that is not a string
620
+ noteAt(site, STYLE_ISSUE.BAD_VALUE, text);
621
+ return null;
622
+ }
623
+ const c = sigmaColor(text);
624
+ if (!c.read) {
625
+ noteAt(site, STYLE_ISSUE.BAD_VALUE, text);
626
+ }
627
+ return { color: c.color, alpha: c.alpha };
628
+ }
629
+
529
630
  /**
530
631
  * A color given as an object: only GEXF and Gephi write one, as channels.
531
632
  * @param raw - the object
@@ -557,10 +658,11 @@ function graphvizCanon(
557
658
  site: CanonSite,
558
659
  options: CanonColorOptions,
559
660
  ): CanonColor | null {
560
- const g = graphvizColor(text, dialect === "x11" ? null : (options.scheme ?? null), options.use ?? "line");
661
+ const x11 = dialect === "x11";
662
+ const g = graphvizColor(text, x11 ? null : (options.scheme ?? null), options.use ?? "line", !x11);
561
663
  if (g.unknown) {
562
664
  noteAt(site, STYLE_ISSUE.BAD_VALUE, text);
563
- if (dialect === "x11") {
665
+ if (x11) {
564
666
  return null;
565
667
  }
566
668
  }