@graphty/graph-io 0.3.48 → 0.3.50

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 (600) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-BRXsll0T.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-BRXsll0T.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-yl0f_qLO.js} +931 -164
  6. package/dist/chunks/block-yl0f_qLO.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-DizmppHy.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-DizmppHy.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-CmvJXYeH.js} +67 -16
  18. package/dist/chunks/credentials-CmvJXYeH.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-Dhez_Cew.js} +11 -2
  24. package/dist/chunks/descriptor-Dhez_Cew.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-7Jkpg0yd.js} +1788 -133
  26. package/dist/chunks/emit-7Jkpg0yd.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-ChjL5fmP.js → exporter-1Ajud15J.js} +9 -8
  32. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-1Ajud15J.js.map} +1 -1
  33. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-B6yvL3wy.js} +7 -7
  34. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-B6yvL3wy.js.map} +1 -1
  35. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  36. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-CA5q8ROP.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-CA5q8ROP.js.map} +1 -1
  39. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-CQQZFJ2v.js} +1284 -156
  40. package/dist/chunks/exporter-CQQZFJ2v.js.map +1 -0
  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-Dc21MAdg.js} +387 -31
  44. package/dist/chunks/generic-Dc21MAdg.js.map +1 -0
  45. package/dist/chunks/{importer-B87_fmVx.js → importer-C6NVpCXp.js} +327 -84
  46. package/dist/chunks/importer-C6NVpCXp.js.map +1 -0
  47. package/dist/chunks/{importer-DPZDN40-.js → importer-CKFe4q54.js} +25 -17
  48. package/dist/chunks/importer-CKFe4q54.js.map +1 -0
  49. package/dist/chunks/{importer-Bji2MeWr.js → importer-CKbUbsJA.js} +13 -10
  50. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-CKbUbsJA.js.map} +1 -1
  51. package/dist/chunks/{importer-CB_zV5_L.js → importer-ClCsdgTJ.js} +208 -1104
  52. package/dist/chunks/importer-ClCsdgTJ.js.map +1 -0
  53. package/dist/chunks/{importer-e3huMZbm.js → importer-CyVZTrf0.js} +14 -10
  54. package/dist/chunks/importer-CyVZTrf0.js.map +1 -0
  55. package/dist/chunks/{importer-CVT-JyDE.js → importer-DgG4v1Ms.js} +1537 -355
  56. package/dist/chunks/importer-DgG4v1Ms.js.map +1 -0
  57. package/dist/chunks/{importer-Cyy6UseH.js → importer-asFUrIsj.js} +66 -13
  58. package/dist/chunks/importer-asFUrIsj.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-IVRq2Uoo.js} +282 -74
  64. package/dist/chunks/lexicon-IVRq2Uoo.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-Cy3_SHRZ.js +79 -0
  72. package/dist/chunks/round-trip-Cy3_SHRZ.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-BXwVbza3.js} +5 -5
  74. package/dist/chunks/sigv4-BXwVbza3.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CAVmBLgp.js} +1237 -138
  76. package/dist/chunks/styles-CAVmBLgp.js.map +1 -0
  77. package/dist/chunks/styles-CPczw1Jz.js +1928 -0
  78. package/dist/chunks/styles-CPczw1Jz.js.map +1 -0
  79. package/dist/chunks/styles-boK6Ln54.js +2847 -0
  80. package/dist/chunks/styles-boK6Ln54.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-XeFBQ6VS.js} +506 -175
  82. package/dist/chunks/styles-yed-XeFBQ6VS.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 +8 -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 +848 -194
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +230 -193
  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 +141 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +32 -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 +439 -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/exporter.d.ts.map +1 -1
  137. package/dist/src/formats/dot/exporter.js +34 -2
  138. package/dist/src/formats/dot/exporter.js.map +1 -1
  139. package/dist/src/formats/dot/importer.d.ts +6 -1
  140. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  141. package/dist/src/formats/dot/importer.js +170 -33
  142. package/dist/src/formats/dot/importer.js.map +1 -1
  143. package/dist/src/formats/dot/index.d.ts +3 -1
  144. package/dist/src/formats/dot/index.d.ts.map +1 -1
  145. package/dist/src/formats/dot/index.js +2 -1
  146. package/dist/src/formats/dot/index.js.map +1 -1
  147. package/dist/src/formats/dot/label-places.d.ts +41 -0
  148. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  149. package/dist/src/formats/dot/label-places.js +185 -0
  150. package/dist/src/formats/dot/label-places.js.map +1 -0
  151. package/dist/src/formats/dot/names.d.ts +13 -0
  152. package/dist/src/formats/dot/names.d.ts.map +1 -1
  153. package/dist/src/formats/dot/names.js +13 -0
  154. package/dist/src/formats/dot/names.js.map +1 -1
  155. package/dist/src/formats/dot/record.d.ts +50 -0
  156. package/dist/src/formats/dot/record.d.ts.map +1 -0
  157. package/dist/src/formats/dot/record.js +275 -0
  158. package/dist/src/formats/dot/record.js.map +1 -0
  159. package/dist/src/formats/dot/styles.d.ts +72 -2
  160. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  161. package/dist/src/formats/dot/styles.js +1500 -119
  162. package/dist/src/formats/dot/styles.js.map +1 -1
  163. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  164. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  165. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  166. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  167. package/dist/src/formats/gexf/importer.d.ts +7 -0
  168. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  169. package/dist/src/formats/gexf/importer.js +41 -5
  170. package/dist/src/formats/gexf/importer.js.map +1 -1
  171. package/dist/src/formats/gexf/preview.d.ts +77 -0
  172. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  173. package/dist/src/formats/gexf/preview.js +191 -0
  174. package/dist/src/formats/gexf/preview.js.map +1 -0
  175. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  176. package/dist/src/formats/gexf/schema.js +2 -1
  177. package/dist/src/formats/gexf/schema.js.map +1 -1
  178. package/dist/src/formats/gexf/styles.d.ts +58 -31
  179. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  180. package/dist/src/formats/gexf/styles.js +848 -225
  181. package/dist/src/formats/gexf/styles.js.map +1 -1
  182. package/dist/src/formats/gml/importer.d.ts +5 -2
  183. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  184. package/dist/src/formats/gml/importer.js +258 -71
  185. package/dist/src/formats/gml/importer.js.map +1 -1
  186. package/dist/src/formats/gml/index.d.ts +1 -1
  187. package/dist/src/formats/gml/index.d.ts.map +1 -1
  188. package/dist/src/formats/gml/index.js +1 -1
  189. package/dist/src/formats/gml/index.js.map +1 -1
  190. package/dist/src/formats/gml/positions.d.ts +7 -0
  191. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  192. package/dist/src/formats/gml/positions.js +29 -7
  193. package/dist/src/formats/gml/positions.js.map +1 -1
  194. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  195. package/dist/src/formats/gml/styles.js +754 -102
  196. package/dist/src/formats/gml/styles.js.map +1 -1
  197. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/styles-plain.js +6 -10
  199. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  200. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  201. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  202. package/dist/src/formats/graphml/styles-yed.js +695 -164
  203. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  204. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  205. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  206. package/dist/src/formats/graphml/styles-yfiles3.js +431 -64
  207. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  208. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  209. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  210. package/dist/src/formats/graphml/yfiles.js +16 -6
  211. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  212. package/dist/src/formats/json/dialect.d.ts +3 -2
  213. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  214. package/dist/src/formats/json/dialect.js +39 -5
  215. package/dist/src/formats/json/dialect.js.map +1 -1
  216. package/dist/src/formats/json/importer.d.ts +13 -2
  217. package/dist/src/formats/json/importer.d.ts.map +1 -1
  218. package/dist/src/formats/json/importer.js +42 -6
  219. package/dist/src/formats/json/importer.js.map +1 -1
  220. package/dist/src/formats/json/index.d.ts +1 -1
  221. package/dist/src/formats/json/index.d.ts.map +1 -1
  222. package/dist/src/formats/json/index.js +1 -1
  223. package/dist/src/formats/json/index.js.map +1 -1
  224. package/dist/src/formats/json/positions.d.ts +5 -2
  225. package/dist/src/formats/json/positions.d.ts.map +1 -1
  226. package/dist/src/formats/json/positions.js +20 -4
  227. package/dist/src/formats/json/positions.js.map +1 -1
  228. package/dist/src/formats/json/styles.d.ts +12 -1
  229. package/dist/src/formats/json/styles.d.ts.map +1 -1
  230. package/dist/src/formats/json/styles.js +1843 -136
  231. package/dist/src/formats/json/styles.js.map +1 -1
  232. package/dist/src/formats/pajek/draw.d.ts +104 -0
  233. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  234. package/dist/src/formats/pajek/draw.js +382 -0
  235. package/dist/src/formats/pajek/draw.js.map +1 -0
  236. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  237. package/dist/src/formats/pajek/exporter.js +70 -51
  238. package/dist/src/formats/pajek/exporter.js.map +1 -1
  239. package/dist/src/formats/pajek/importer.d.ts +9 -0
  240. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  241. package/dist/src/formats/pajek/importer.js +233 -102
  242. package/dist/src/formats/pajek/importer.js.map +1 -1
  243. package/dist/src/formats/pajek/index.d.ts +1 -0
  244. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  245. package/dist/src/formats/pajek/index.js.map +1 -1
  246. package/dist/src/formats/pajek/styles.d.ts +15 -7
  247. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  248. package/dist/src/formats/pajek/styles.js +1395 -114
  249. package/dist/src/formats/pajek/styles.js.map +1 -1
  250. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  251. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  252. package/dist/src/formats/pajek/syntax.js +26 -2
  253. package/dist/src/formats/pajek/syntax.js.map +1 -1
  254. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  255. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  256. package/dist/src/formats/xgmml/emit.js +65 -5
  257. package/dist/src/formats/xgmml/emit.js.map +1 -1
  258. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  259. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  260. package/dist/src/formats/xgmml/styles.js +277 -60
  261. package/dist/src/formats/xgmml/styles.js.map +1 -1
  262. package/dist/src/index.d.ts +6 -5
  263. package/dist/src/index.d.ts.map +1 -1
  264. package/dist/src/index.js +6 -5
  265. package/dist/src/index.js.map +1 -1
  266. package/dist/src/positions/convert.d.ts.map +1 -1
  267. package/dist/src/positions/convert.js +11 -1
  268. package/dist/src/positions/convert.js.map +1 -1
  269. package/dist/src/positions/extract.d.ts.map +1 -1
  270. package/dist/src/positions/extract.js +53 -1
  271. package/dist/src/positions/extract.js.map +1 -1
  272. package/dist/src/positions/index.d.ts +1 -1
  273. package/dist/src/positions/index.d.ts.map +1 -1
  274. package/dist/src/positions/types.d.ts +59 -0
  275. package/dist/src/positions/types.d.ts.map +1 -1
  276. package/dist/src/sources/builtins.d.ts +1 -1
  277. package/dist/src/sources/builtins.d.ts.map +1 -1
  278. package/dist/src/sources/builtins.js +8 -2
  279. package/dist/src/sources/builtins.js.map +1 -1
  280. package/dist/src/sources/context.d.ts.map +1 -1
  281. package/dist/src/sources/context.js +1 -0
  282. package/dist/src/sources/context.js.map +1 -1
  283. package/dist/src/sources/credentials.d.ts +50 -1
  284. package/dist/src/sources/credentials.d.ts.map +1 -1
  285. package/dist/src/sources/credentials.js +69 -0
  286. package/dist/src/sources/credentials.js.map +1 -1
  287. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  288. package/dist/src/sources/cypher/descriptor.js +5 -0
  289. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  290. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  291. package/dist/src/sources/cypher/index.js +125 -18
  292. package/dist/src/sources/cypher/index.js.map +1 -1
  293. package/dist/src/sources/cypher/params.d.ts +1 -1
  294. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  295. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  296. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  297. package/dist/src/sources/cypher/query-builder.js +31 -0
  298. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  299. package/dist/src/sources/ids.d.ts +5 -0
  300. package/dist/src/sources/ids.d.ts.map +1 -1
  301. package/dist/src/sources/ids.js +5 -0
  302. package/dist/src/sources/ids.js.map +1 -1
  303. package/dist/src/sources/params.d.ts +3 -0
  304. package/dist/src/sources/params.d.ts.map +1 -1
  305. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  306. package/dist/src/sources/rest/descriptor.js +9 -0
  307. package/dist/src/sources/rest/descriptor.js.map +1 -1
  308. package/dist/src/sources/rest/openalex.d.ts +4 -2
  309. package/dist/src/sources/rest/openalex.d.ts.map +1 -1
  310. package/dist/src/sources/rest/openalex.js +4 -2
  311. package/dist/src/sources/rest/openalex.js.map +1 -1
  312. package/dist/src/sources/rest/source.d.ts.map +1 -1
  313. package/dist/src/sources/rest/source.js +38 -0
  314. package/dist/src/sources/rest/source.js.map +1 -1
  315. package/dist/src/sources/run.d.ts +2 -0
  316. package/dist/src/sources/run.d.ts.map +1 -1
  317. package/dist/src/sources/run.js +30 -3
  318. package/dist/src/sources/run.js.map +1 -1
  319. package/dist/src/sources/sigv4.d.ts +5 -3
  320. package/dist/src/sources/sigv4.d.ts.map +1 -1
  321. package/dist/src/sources/sigv4.js +6 -4
  322. package/dist/src/sources/sigv4.js.map +1 -1
  323. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  324. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  325. package/dist/src/sources/sparql/descriptor.js +64 -0
  326. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  327. package/dist/src/sources/sparql/index.d.ts +28 -0
  328. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  329. package/dist/src/sources/sparql/index.js +327 -0
  330. package/dist/src/sources/sparql/index.js.map +1 -0
  331. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  332. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  333. package/dist/src/sources/sparql/ntriples.js +180 -0
  334. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  335. package/dist/src/sources/sparql/params.d.ts +27 -0
  336. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  337. package/dist/src/sources/sparql/params.js +5 -0
  338. package/dist/src/sources/sparql/params.js.map +1 -0
  339. package/dist/src/sources/sparql/query.d.ts +73 -0
  340. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  341. package/dist/src/sources/sparql/query.js +164 -0
  342. package/dist/src/sources/sparql/query.js.map +1 -0
  343. package/dist/src/sources/types.d.ts +60 -0
  344. package/dist/src/sources/types.d.ts.map +1 -1
  345. package/dist/src/styles/annotations.d.ts +61 -5
  346. package/dist/src/styles/annotations.d.ts.map +1 -1
  347. package/dist/src/styles/annotations.js +130 -22
  348. package/dist/src/styles/annotations.js.map +1 -1
  349. package/dist/src/styles/canon/bends.d.ts +46 -0
  350. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  351. package/dist/src/styles/canon/bends.js +123 -0
  352. package/dist/src/styles/canon/bends.js.map +1 -1
  353. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  354. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  355. package/dist/src/styles/canon/color-tables.js +10 -4
  356. package/dist/src/styles/canon/color-tables.js.map +1 -1
  357. package/dist/src/styles/canon/color.d.ts +3 -1
  358. package/dist/src/styles/canon/color.d.ts.map +1 -1
  359. package/dist/src/styles/canon/color.js +103 -3
  360. package/dist/src/styles/canon/color.js.map +1 -1
  361. package/dist/src/styles/canon/enums.d.ts +2 -2
  362. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  363. package/dist/src/styles/canon/enums.js +89 -7
  364. package/dist/src/styles/canon/enums.js.map +1 -1
  365. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  366. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  367. package/dist/src/styles/canon/graphviz.js +57 -9
  368. package/dist/src/styles/canon/graphviz.js.map +1 -1
  369. package/dist/src/styles/canon/number.d.ts +8 -0
  370. package/dist/src/styles/canon/number.d.ts.map +1 -1
  371. package/dist/src/styles/canon/number.js +18 -0
  372. package/dist/src/styles/canon/number.js.map +1 -1
  373. package/dist/src/styles/canon/text.d.ts +29 -2
  374. package/dist/src/styles/canon/text.d.ts.map +1 -1
  375. package/dist/src/styles/canon/text.js +156 -16
  376. package/dist/src/styles/canon/text.js.map +1 -1
  377. package/dist/src/styles/codes.d.ts +2 -0
  378. package/dist/src/styles/codes.d.ts.map +1 -1
  379. package/dist/src/styles/codes.js +2 -0
  380. package/dist/src/styles/codes.js.map +1 -1
  381. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  382. package/dist/src/styles/cyjs/cascade.js +1139 -79
  383. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  384. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  385. package/dist/src/styles/cyjs/defaults-table.js +4 -0
  386. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  387. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  388. package/dist/src/styles/cyjs/emit.js +232 -10
  389. package/dist/src/styles/cyjs/emit.js.map +1 -1
  390. package/dist/src/styles/cyjs/face.d.ts +20 -0
  391. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  392. package/dist/src/styles/cyjs/face.js +332 -0
  393. package/dist/src/styles/cyjs/face.js.map +1 -0
  394. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  395. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  396. package/dist/src/styles/cyjs/mappers.js +475 -26
  397. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  398. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  399. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  400. package/dist/src/styles/cyjs/routes.js +360 -0
  401. package/dist/src/styles/cyjs/routes.js.map +1 -0
  402. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  403. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  404. package/dist/src/styles/cytoscape/charts.js +560 -0
  405. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  406. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  407. package/dist/src/styles/cytoscape/emit.js +156 -48
  408. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  409. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  410. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  411. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  412. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  413. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  414. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  415. package/dist/src/styles/cytoscape/mappings.js +92 -0
  416. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  417. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  418. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  419. package/dist/src/styles/cytoscape/resolve.js +623 -17
  420. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  421. package/dist/src/styles/defaults.d.ts +46 -26
  422. package/dist/src/styles/defaults.d.ts.map +1 -1
  423. package/dist/src/styles/defaults.js +308 -71
  424. package/dist/src/styles/defaults.js.map +1 -1
  425. package/dist/src/styles/index.d.ts +4 -3
  426. package/dist/src/styles/index.d.ts.map +1 -1
  427. package/dist/src/styles/index.js +3 -2
  428. package/dist/src/styles/index.js.map +1 -1
  429. package/dist/src/styles/internal.d.ts +1 -0
  430. package/dist/src/styles/internal.d.ts.map +1 -1
  431. package/dist/src/styles/internal.js +1 -0
  432. package/dist/src/styles/internal.js.map +1 -1
  433. package/dist/src/styles/io/generic.d.ts.map +1 -1
  434. package/dist/src/styles/io/generic.js +56 -16
  435. package/dist/src/styles/io/generic.js.map +1 -1
  436. package/dist/src/styles/io/round-trip.d.ts +56 -0
  437. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  438. package/dist/src/styles/io/round-trip.js +138 -0
  439. package/dist/src/styles/io/round-trip.js.map +1 -0
  440. package/dist/src/styles/io/writer.d.ts.map +1 -1
  441. package/dist/src/styles/io/writer.js +6 -1
  442. package/dist/src/styles/io/writer.js.map +1 -1
  443. package/dist/src/styles/notes.d.ts.map +1 -1
  444. package/dist/src/styles/notes.js +1 -0
  445. package/dist/src/styles/notes.js.map +1 -1
  446. package/dist/src/styles/plan/features.d.ts +1 -1
  447. package/dist/src/styles/plan/features.d.ts.map +1 -1
  448. package/dist/src/styles/plan/features.js +22 -2
  449. package/dist/src/styles/plan/features.js.map +1 -1
  450. package/dist/src/styles/plan/index.d.ts +1 -1
  451. package/dist/src/styles/plan/index.d.ts.map +1 -1
  452. package/dist/src/styles/plan/index.js +1 -1
  453. package/dist/src/styles/plan/index.js.map +1 -1
  454. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  455. package/dist/src/styles/plan/plan.js +61 -4
  456. package/dist/src/styles/plan/plan.js.map +1 -1
  457. package/dist/src/styles/plan/resolve.d.ts +11 -0
  458. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  459. package/dist/src/styles/plan/resolve.js +40 -4
  460. package/dist/src/styles/plan/resolve.js.map +1 -1
  461. package/dist/src/styles/slots.d.ts +14 -0
  462. package/dist/src/styles/slots.d.ts.map +1 -0
  463. package/dist/src/styles/slots.js +20 -0
  464. package/dist/src/styles/slots.js.map +1 -0
  465. package/dist/src/styles/types.d.ts +687 -6
  466. package/dist/src/styles/types.d.ts.map +1 -1
  467. package/dist/src/styles/vocabulary.d.ts +3 -2
  468. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  469. package/dist/src/styles/vocabulary.js +224 -0
  470. package/dist/src/styles/vocabulary.js.map +1 -1
  471. package/dist/styles.js +30 -239
  472. package/dist/styles.js.map +1 -1
  473. package/dist/xgmml.js +3 -3
  474. package/package.json +27 -7
  475. package/src/formats/cx/importer.ts +6 -1
  476. package/src/formats/cx/styles.ts +143 -9
  477. package/src/formats/cx2/importer.ts +1 -0
  478. package/src/formats/cx2/styles.ts +3 -1
  479. package/src/formats/cys/importer.ts +1 -0
  480. package/src/formats/cys/styles.ts +27 -5
  481. package/src/formats/dot/drawing.ts +799 -0
  482. package/src/formats/dot/exporter.ts +37 -1
  483. package/src/formats/dot/importer.ts +192 -36
  484. package/src/formats/dot/index.ts +3 -1
  485. package/src/formats/dot/label-places.ts +241 -0
  486. package/src/formats/dot/names.ts +15 -0
  487. package/src/formats/dot/record.ts +336 -0
  488. package/src/formats/dot/styles.ts +1702 -149
  489. package/src/formats/gexf/dialog-metrics.ts +61 -0
  490. package/src/formats/gexf/importer.ts +50 -5
  491. package/src/formats/gexf/preview.ts +217 -0
  492. package/src/formats/gexf/schema.ts +2 -1
  493. package/src/formats/gexf/styles.ts +1099 -245
  494. package/src/formats/gml/importer.ts +291 -76
  495. package/src/formats/gml/index.ts +1 -1
  496. package/src/formats/gml/positions.ts +29 -7
  497. package/src/formats/gml/styles.ts +852 -110
  498. package/src/formats/graphml/styles-plain.ts +6 -15
  499. package/src/formats/graphml/styles-yed.ts +765 -176
  500. package/src/formats/graphml/styles-yfiles3.ts +487 -63
  501. package/src/formats/graphml/yfiles.ts +19 -6
  502. package/src/formats/json/dialect.ts +41 -5
  503. package/src/formats/json/importer.ts +59 -7
  504. package/src/formats/json/index.ts +1 -0
  505. package/src/formats/json/positions.ts +22 -5
  506. package/src/formats/json/styles.ts +2123 -171
  507. package/src/formats/pajek/draw.ts +469 -0
  508. package/src/formats/pajek/exporter.ts +81 -49
  509. package/src/formats/pajek/importer.ts +278 -103
  510. package/src/formats/pajek/index.ts +1 -0
  511. package/src/formats/pajek/styles.ts +1506 -133
  512. package/src/formats/pajek/syntax.ts +27 -2
  513. package/src/formats/xgmml/emit.ts +73 -5
  514. package/src/formats/xgmml/styles.ts +330 -71
  515. package/src/index.ts +12 -1
  516. package/src/positions/convert.ts +12 -1
  517. package/src/positions/extract.ts +55 -1
  518. package/src/positions/index.ts +1 -0
  519. package/src/positions/types.ts +60 -0
  520. package/src/sources/builtins.ts +8 -1
  521. package/src/sources/context.ts +1 -0
  522. package/src/sources/credentials.ts +90 -1
  523. package/src/sources/cypher/descriptor.ts +7 -1
  524. package/src/sources/cypher/index.ts +149 -18
  525. package/src/sources/cypher/params.ts +1 -1
  526. package/src/sources/cypher/query-builder.ts +33 -0
  527. package/src/sources/ids.ts +6 -0
  528. package/src/sources/params.ts +3 -0
  529. package/src/sources/rest/descriptor.ts +9 -0
  530. package/src/sources/rest/openalex.ts +4 -2
  531. package/src/sources/rest/source.ts +41 -0
  532. package/src/sources/run.ts +35 -3
  533. package/src/sources/sigv4.ts +6 -4
  534. package/src/sources/sparql/descriptor.ts +67 -0
  535. package/src/sources/sparql/index.ts +371 -0
  536. package/src/sources/sparql/ntriples.ts +219 -0
  537. package/src/sources/sparql/params.ts +28 -0
  538. package/src/sources/sparql/query.ts +216 -0
  539. package/src/sources/types.ts +68 -0
  540. package/src/styles/annotations.ts +201 -27
  541. package/src/styles/canon/bends.ts +137 -0
  542. package/src/styles/canon/color-tables.ts +10 -4
  543. package/src/styles/canon/color.ts +105 -3
  544. package/src/styles/canon/enums.ts +107 -8
  545. package/src/styles/canon/graphviz.ts +71 -10
  546. package/src/styles/canon/number.ts +19 -0
  547. package/src/styles/canon/text.ts +187 -16
  548. package/src/styles/codes.ts +2 -0
  549. package/src/styles/cyjs/cascade.ts +1303 -84
  550. package/src/styles/cyjs/defaults-table.ts +4 -0
  551. package/src/styles/cyjs/emit.ts +268 -14
  552. package/src/styles/cyjs/face.ts +372 -0
  553. package/src/styles/cyjs/mappers.ts +506 -27
  554. package/src/styles/cyjs/routes.ts +432 -0
  555. package/src/styles/cytoscape/charts.ts +684 -0
  556. package/src/styles/cytoscape/emit.ts +170 -48
  557. package/src/styles/cytoscape/lexicon.ts +431 -78
  558. package/src/styles/cytoscape/mappings.ts +108 -0
  559. package/src/styles/cytoscape/resolve.ts +741 -17
  560. package/src/styles/defaults.ts +417 -108
  561. package/src/styles/index.ts +5 -0
  562. package/src/styles/internal.ts +1 -0
  563. package/src/styles/io/generic.ts +79 -23
  564. package/src/styles/io/round-trip.ts +202 -0
  565. package/src/styles/io/writer.ts +6 -1
  566. package/src/styles/notes.ts +1 -0
  567. package/src/styles/plan/features.ts +23 -2
  568. package/src/styles/plan/index.ts +1 -1
  569. package/src/styles/plan/plan.ts +69 -5
  570. package/src/styles/plan/resolve.ts +47 -4
  571. package/src/styles/slots.ts +25 -0
  572. package/src/styles/types.ts +698 -5
  573. package/src/styles/vocabulary.ts +232 -2
  574. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  575. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  576. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  577. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  578. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  579. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  580. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  581. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  582. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  583. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  584. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  585. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  586. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  587. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  588. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  589. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  590. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  591. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  592. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  593. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  594. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  595. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  596. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  597. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  598. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  599. package/dist/chunks/writer-DvHTl36J.js +0 -449
  600. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -15,16 +15,27 @@
15
15
  * property to its Cytoscape.js default, whatever the rules beneath say.
16
16
  */
17
17
 
18
+ import { canonColor } from "../canon/color.js";
18
19
  import { CSS_COLORS } from "../canon/color-tables.js";
19
20
  import { canonEnum } from "../canon/enums.js";
20
21
  import { num6 } from "../canon/number.js";
21
22
  import type { CanonSite } from "../canon/site.js";
22
23
  import { STYLE_ISSUE } from "../codes.js";
23
24
  import type { StyleTarget, StyleValue } from "../types.js";
25
+ import { CYJS_FACE_PROPERTIES } from "./face.js";
24
26
 
25
27
  /** How Cytoscape.js types a property's value. */
26
28
  export type CyjsValueType =
27
- "color" | "zeroOne" | "size" | "nodeSize" | "positive" | "text" | "fontFamily" | "fontWeight" | "enum";
29
+ | "color"
30
+ | "zeroOne"
31
+ | "size"
32
+ | "signedSize"
33
+ | "nodeSize"
34
+ | "positive"
35
+ | "text"
36
+ | "fontFamily"
37
+ | "fontWeight"
38
+ | "enum";
28
39
 
29
40
  /** One property graph-io carries: the neutral property it sets (or a part it combines) and how it is parsed. */
30
41
  export interface CyjsPropertySpec {
@@ -109,7 +120,8 @@ const FONT_WEIGHTS: readonly (string | number)[] = [
109
120
  800,
110
121
  900,
111
122
  ];
112
- const CURVES = [
123
+ /** Cytoscape.js's curve styles. */
124
+ export const CYJS_CURVE_STYLES = [
113
125
  "bezier",
114
126
  "unbundled-bezier",
115
127
  "haystack",
@@ -141,19 +153,330 @@ const LABEL: [string, CyjsPropertySpec][] = [
141
153
  ["visibility", { property: "_visibility", type: "enum", enums: ["hidden", "visible"] }],
142
154
  ["display", { property: "_display", type: "enum", enums: ["element", "none"] }],
143
155
  ["opacity", { property: "opacity", type: "zeroOne" }],
156
+ ["text-transform", { property: "_transform", type: "enum", enums: ["none", "uppercase", "lowercase"] }],
157
+ ["text-wrap", { property: "_wrap", type: "enum", enums: ["none", "wrap", "ellipsis"] }],
158
+ ["text-overflow-wrap", { property: "_overflowWrap", type: "enum", enums: ["whitespace", "anywhere"] }],
159
+ // how the lines line up; `auto` follows the horizontal alignment (`combineLabelText`)
160
+ ["text-justification", { property: "_justification", type: "enum", enums: ["auto", "left", "center", "right"] }],
161
+ // a width only `text-wrap: wrap` wraps at, so it is combined with the wrap afterward (`combineParts`)
162
+ ["text-max-width", { property: "_maxWidth", type: "size" }],
163
+ // the outline and the background box draw only with a width and an opacity (`combineLabelDress`)
164
+ ["text-outline-color", { property: "_outlineColor", type: "color" }],
165
+ ["text-outline-width", { property: "_outlineWidth", type: "size" }],
166
+ ["text-outline-opacity", { property: "_outlineOpacity", type: "zeroOne" }],
167
+ ["text-background-color", { property: "_backgroundColor", type: "color" }],
168
+ ["text-background-opacity", { property: "_backgroundOpacity", type: "zeroOne" }],
169
+ ["text-background-padding", { property: "_backgroundPadding", type: "size" }],
170
+ [
171
+ "text-background-shape",
172
+ {
173
+ property: "_backgroundShape",
174
+ type: "enum",
175
+ enums: ["rectangle", "round-rectangle", "roundrectangle", "circle"],
176
+ },
177
+ ],
178
+ ["text-rotation", { property: "_rotation", type: "text" }],
179
+ // the words' own opacity, drawn times the element's (`combineLabelOpacity`)
180
+ ["text-opacity", { property: "_textOpacity", type: "zeroOne" }],
181
+ // the label moved right and down by this many pixels from where its alignment puts it, a node's and an edge's
182
+ ["text-margin-x", { property: "labelOffsetX", type: "signedSize" }],
183
+ ["text-margin-y", { property: "labelOffsetY", type: "signedSize" }],
184
+ // the line round the label's box draws only with a width and an opacity above 0 (`combineLabelDress`)
185
+ ["text-border-color", { property: "_textBorderColor", type: "color" }],
186
+ ["text-border-width", { property: "_textBorderWidth", type: "size" }],
187
+ ["text-border-opacity", { property: "_textBorderOpacity", type: "zeroOne" }],
188
+ [
189
+ "text-border-style",
190
+ { property: "_textBorderStyle", type: "enum", enums: ["solid", "dotted", "dashed", "double"] },
191
+ ],
144
192
  ];
145
193
 
194
+ /** Cytoscape.js's `background-gradient-direction` values. */
195
+ const GRADIENT_DIRECTIONS = [
196
+ "to-bottom",
197
+ "to-top",
198
+ "to-left",
199
+ "to-right",
200
+ "to-bottom-right",
201
+ "to-bottom-left",
202
+ "to-top-right",
203
+ "to-top-left",
204
+ "to-right-bottom",
205
+ "to-left-bottom",
206
+ "to-right-top",
207
+ "to-left-top",
208
+ ];
209
+
210
+ /**
211
+ * The pixels of one `em`: Cytoscape.js reads it as its container's font size (`getEmSizeInPixels`, cytoscape.js
212
+ * 3.34.3 dist/cytoscape.cjs.js line 16896), 16 in a page that leaves the font size at the browser's default.
213
+ */
214
+ const EM_PX = 16;
215
+
216
+ /**
217
+ * Cytoscape.js's `shape-polygon-points` (`x y` pairs, y down, commas or spaces between) as neutral `shapePoints`.
218
+ * @param text - the points
219
+ * @returns `x,y` pairs with y up, or null when they are not pairs of numbers
220
+ */
221
+ function cyjsPointsToNeutral(text: string): string | null {
222
+ const n = text
223
+ .trim()
224
+ .split(/[\s,]+/)
225
+ .map(Number);
226
+ if (n.length < 6 || n.length % 2 !== 0 || !n.every((v) => Number.isFinite(v))) {
227
+ return null;
228
+ }
229
+ const pairs: string[] = [];
230
+ for (let i = 0; i < n.length; i += 2) {
231
+ pairs.push(`${String(round6(n[i]))},${String(round6(-n[i + 1]))}`);
232
+ }
233
+ return pairs.join(" ");
234
+ }
235
+
236
+ /**
237
+ * Neutral `shapePoints` as Cytoscape.js's `shape-polygon-points`.
238
+ * @param points - `x,y` pairs with y up
239
+ * @returns `x y` pairs with y down, or null when they are not pairs of numbers
240
+ */
241
+ export function neutralPointsToCyjs(points: string): string | null {
242
+ const n = points
243
+ .trim()
244
+ .split(/[\s,]+/)
245
+ .map(Number);
246
+ if (n.length < 6 || n.length % 2 !== 0 || !n.every((v) => Number.isFinite(v))) {
247
+ return null;
248
+ }
249
+ const pairs: string[] = [];
250
+ for (let i = 0; i < n.length; i += 2) {
251
+ pairs.push(`${String(round6(n[i]))} ${String(round6(-n[i + 1]))}`);
252
+ }
253
+ return pairs.join(" ");
254
+ }
255
+
256
+ /**
257
+ * A coordinate to six decimals, with no negative zero.
258
+ * @param v - the coordinate
259
+ * @returns it rounded
260
+ */
261
+ const round6 = (v: number): number => Math.round(v * 1e6) / 1e6 + 0;
262
+
263
+ /**
264
+ * Cytoscape.js's corners of a heptagon fitted to its box (`generateUnitNgonPointsFitToSquare(7, 0)`): a regular
265
+ * heptagon with a corner up, stretched until it fills the box both ways.
266
+ * @returns the corners as `x,y` fractions of the half width and half height, y up
267
+ */
268
+ function fittedHeptagon(): string {
269
+ const corners = Array.from({ length: 7 }, (_, i): [number, number] => {
270
+ const angle = Math.PI / 2 + (2 * Math.PI * i) / 7;
271
+ return [Math.cos(angle), Math.sin(angle)];
272
+ });
273
+ const [x0, x1] = [Math.min(...corners.map(([x]) => x)), Math.max(...corners.map(([x]) => x))];
274
+ const [y0, y1] = [Math.min(...corners.map(([, y]) => y)), Math.max(...corners.map(([, y]) => y))];
275
+ return corners
276
+ .map(([x, y]) => `${round6((2 * (x - x0)) / (x1 - x0) - 1)},${round6((2 * (y - y0)) / (y1 - y0) - 1)}`)
277
+ .join(" ");
278
+ }
279
+
280
+ /**
281
+ * The Cytoscape.js node shapes no neutral shape names, with the corners Cytoscape.js draws each at (cytoscape.js
282
+ * 3.34.3 dist/cytoscape.cjs.js lines 27976-28008); the round ones are `other:round-polygon` over the same corners.
283
+ */
284
+ const CYJS_POLYGON_SHAPES: ReadonlyMap<string, string> = new Map([
285
+ ["heptagon", fittedHeptagon()],
286
+ ["round-heptagon", fittedHeptagon()],
287
+ ["tag", "-1,-1 0.25,-1 1,0 0.25,1 -1,1"],
288
+ ["round-tag", "-1,-1 0.25,-1 1,0 0.25,1 -1,1"],
289
+ ]);
290
+
291
+ /**
292
+ * Cytoscape.js's polygons drawn with rounded corners (`corner-radius`, by default a tenth of the shorter side),
293
+ * kept as their own `other:` shapes rather than read as their sharp twins.
294
+ */
295
+ const CYJS_ROUND_SHAPES: ReadonlySet<string> = new Set([
296
+ "round-triangle",
297
+ "round-diamond",
298
+ "round-pentagon",
299
+ "round-hexagon",
300
+ "round-octagon",
301
+ ]);
302
+
303
+ /**
304
+ * Draws every Cytoscape.js shape no neutral shape names (`other:heptagon`, `other:tag`) as the polygon Cytoscape.js
305
+ * builds for it: `polygon` with its corners in `shapePoints`.
306
+ * @param values - node values (per element, or a rule's constants), changed in place
307
+ */
308
+ export function cyjsPolygonShapes(values: Record<string, unknown>): void {
309
+ const { shape } = values;
310
+ const pointsOf = (v: unknown): string | undefined =>
311
+ typeof v === "string" && v.startsWith("other:") ? CYJS_POLYGON_SHAPES.get(v.slice("other:".length)) : undefined;
312
+ if (Array.isArray(shape)) {
313
+ const col = shape as (StyleValue | null)[];
314
+ if (!col.some((v) => pointsOf(v) !== undefined)) {
315
+ return;
316
+ }
317
+ const points = Array.isArray(values.shapePoints)
318
+ ? [...(values.shapePoints as (StyleValue | null)[])]
319
+ : new Array<StyleValue | null>(col.length).fill(null);
320
+ values.shape = col.map((v, i) => {
321
+ const p = pointsOf(v);
322
+ if (p === undefined) {
323
+ return v;
324
+ }
325
+ points[i] = p;
326
+ return polygonOf(v);
327
+ });
328
+ values.shapePoints = points;
329
+ return;
330
+ }
331
+ const p = pointsOf(shape);
332
+ if (p !== undefined) {
333
+ values.shape = polygonOf(shape);
334
+ values.shapePoints = p;
335
+ }
336
+ }
337
+
338
+ /**
339
+ * The polygon a Cytoscape.js polygon shape is drawn as: `other:round-polygon` for its round ones.
340
+ * @param shape - the shape, `other:<Cytoscape.js name>`
341
+ * @returns the neutral shape
342
+ */
343
+ function polygonOf(shape: unknown): string {
344
+ return typeof shape === "string" && shape.startsWith("other:round-") ? "other:round-polygon" : "polygon";
345
+ }
346
+
347
+ /** How Cytoscape.js's `line-fill` paints a line, as the neutral gradient kind. */
348
+ const GRADIENT_KINDS: ReadonlyMap<string, string> = new Map([
349
+ ["solid", "none"],
350
+ ["linear-gradient", "linear"],
351
+ ["radial-gradient", "radial"],
352
+ ]);
353
+
354
+ /**
355
+ * A text split at its runs of whitespace that are not inside parentheses: `rgb(0, 0, 0) red` is two words. A run is
356
+ * inside when the next parenthesis after it closes one (as `/\s+(?![^(]*\))/` splits, in one pass).
357
+ * @param text - the text
358
+ * @returns the words
359
+ */
360
+ function wordsOutsideParens(text: string): string[] {
361
+ // whether the next parenthesis at or after each offset is a `)`
362
+ const closes = new Array<boolean>(text.length + 1).fill(false);
363
+ for (let i = text.length - 1; i >= 0; i--) {
364
+ closes[i] = text[i] === ")" || (text[i] !== "(" && closes[i + 1]);
365
+ }
366
+ const words: string[] = [];
367
+ let start = 0;
368
+ let i = 0;
369
+ while (i < text.length) {
370
+ if (!/\s/.test(text[i])) {
371
+ i++;
372
+ continue;
373
+ }
374
+ let end = i + 1;
375
+ while (end < text.length && /\s/.test(text[end])) {
376
+ end++;
377
+ }
378
+ if (!closes[end]) {
379
+ words.push(text.slice(start, i));
380
+ start = end;
381
+ }
382
+ i = end;
383
+ }
384
+ words.push(text.slice(start));
385
+ return words;
386
+ }
387
+
388
+ /**
389
+ * Cytoscape.js's `line-gradient-stop-colors` (colors separated by spaces) as `#rrggbb` colors separated by spaces.
390
+ * @param text - the value
391
+ * @param site - where it was read
392
+ * @returns the colors, or undefined when one does not parse (noted)
393
+ */
394
+ function gradientColors(text: string, site: CanonSite): string | undefined {
395
+ const hexes: string[] = [];
396
+ for (const token of wordsOutsideParens(text.trim())) {
397
+ const c = token === "" ? null : canonColor(token, "css", site);
398
+ if (c === null) {
399
+ return undefined;
400
+ }
401
+ hexes.push(c.color);
402
+ }
403
+ return hexes.join(" ");
404
+ }
405
+
406
+ /**
407
+ * Cytoscape.js's gradient stop colors (colors separated by spaces) as `#rrggbb` colors.
408
+ * @param text - the value
409
+ * @param site - where it was read
410
+ * @returns the colors, none when one does not parse (noted)
411
+ */
412
+ export function gradientStopColors(text: string, site: CanonSite): string[] {
413
+ return gradientColors(text, site)?.split(" ") ?? [];
414
+ }
415
+
416
+ /**
417
+ * Cytoscape.js's `line-gradient-stop-positions` (percentages or fractions separated by spaces) as fractions.
418
+ * @param text - the value
419
+ * @returns the fractions separated by spaces, or undefined when one is not a number
420
+ */
421
+ export function gradientStops(text: string): string | undefined {
422
+ const stops = text
423
+ .trim()
424
+ .split(/\s+/)
425
+ .map((t) => (t.endsWith("%") ? Number.parseFloat(t) / 100 : Number.parseFloat(t)));
426
+ return stops.every((n) => Number.isFinite(n)) ? stops.map((n) => num6(n)).join(" ") : undefined;
427
+ }
428
+
429
+ /** The lengths Cytoscape.js draws at half their value: a bundle's control point step, an outline's offset. */
430
+ const HALVED: ReadonlySet<string> = new Set(["fanSpacing", "outerBorderOffset"]);
431
+
146
432
  /** The node properties graph-io carries, by Cytoscape.js name. */
147
433
  export const CYJS_NODE_PROPERTIES: ReadonlyMap<string, CyjsPropertySpec> = new Map<string, CyjsPropertySpec>([
148
434
  ["background-color", { property: "fill", type: "color" }],
149
435
  ["background-opacity", { property: "fillOpacity", type: "zeroOne" }],
150
436
  ["border-color", { property: "borderColor", type: "color" }],
437
+ // the rings are drawn at their own opacity times the node's (`combineNodeOpacity`)
438
+ ["border-opacity", { property: "_ringOpacity", type: "zeroOne" }],
151
439
  ["border-width", { property: "borderWidth", type: "size" }],
152
440
  ["border-style", { property: "borderStyle", type: "enum", enums: ["solid", "dotted", "dashed", "double"] }],
441
+ // the dashes a dashed border is drawn with and their ends, which decide how it looks (`combineDashes`)
442
+ ["border-dash-pattern", { property: "_dashPattern", type: "text" }],
443
+ ["border-cap", { property: "_dashCap", type: "enum", enums: ["butt", "round", "square"] }],
444
+ // where the border sits against the node's outline: across it, inside it or outside it
445
+ ["border-position", { property: "borderPosition", type: "enum", enums: ["center", "inside", "outside"] }],
446
+ ["outline-color", { property: "outerBorderColor", type: "color" }],
447
+ ["outline-opacity", { property: "_outlineRingOpacity", type: "zeroOne" }],
448
+ ["outline-width", { property: "outerBorderWidth", type: "size" }],
449
+ ["outline-style", { property: "outerBorderStyle", type: "enum", enums: ["solid", "dotted", "dashed", "double"] }],
450
+ ["outline-offset", { property: "outerBorderOffset", type: "size" }],
451
+ ["underlay-color", { property: "underlayColor", type: "color" }],
452
+ ["underlay-opacity", { property: "underlayOpacity", type: "zeroOne" }],
453
+ ["underlay-padding", { property: "underlayPadding", type: "size" }],
454
+ ["underlay-shape", { property: "underlayShape", type: "enum", enums: NODE_SHAPES }],
455
+ ["underlay-corner-radius", { property: "underlayCornerRadius", type: "size" }],
456
+ ["overlay-color", { property: "overlayColor", type: "color" }],
457
+ ["overlay-opacity", { property: "overlayOpacity", type: "zeroOne" }],
458
+ ["overlay-padding", { property: "overlayPadding", type: "size" }],
459
+ ["overlay-shape", { property: "overlayShape", type: "enum", enums: NODE_SHAPES }],
460
+ ["overlay-corner-radius", { property: "overlayCornerRadius", type: "size" }],
153
461
  ["shape", { property: "shape", type: "enum", enums: NODE_SHAPES }],
462
+ ["shape-polygon-points", { property: "shapePoints", type: "text" }],
154
463
  ["corner-radius", { property: "cornerRadius", type: "size" }],
155
464
  ["width", { property: "width", type: "nodeSize" }],
156
465
  ["height", { property: "height", type: "nodeSize" }],
466
+ // a node is drawn this much larger on every side (`nodeSizes`)
467
+ ["padding", { property: "_padding", type: "text" }],
468
+ // how a compound parent is sized round its children (`groupBoxes`)
469
+ [
470
+ "padding-relative-to",
471
+ { property: "_paddingOf", type: "enum", enums: ["width", "height", "average", "min", "max"] },
472
+ ],
473
+ ["min-width", { property: "_minWidth", type: "text" }],
474
+ ["min-height", { property: "_minHeight", type: "text" }],
475
+ ["min-width-bias-left", { property: "_biasLeft", type: "text" }],
476
+ ["min-width-bias-right", { property: "_biasRight", type: "text" }],
477
+ ["min-height-bias-top", { property: "_biasTop", type: "text" }],
478
+ ["min-height-bias-bottom", { property: "_biasBottom", type: "text" }],
479
+ ["compound-sizing-wrt-labels", { property: "_compoundLabels", type: "enum", enums: ["include", "exclude"] }],
157
480
  [
158
481
  "text-valign",
159
482
  { property: "_valign", type: "enum", enums: ["top", "top-inside", "center", "bottom", "bottom-inside"] },
@@ -162,6 +485,16 @@ export const CYJS_NODE_PROPERTIES: ReadonlyMap<string, CyjsPropertySpec> = new M
162
485
  "text-halign",
163
486
  { property: "_halign", type: "enum", enums: ["left", "left-inside", "center", "right", "right-inside"] },
164
487
  ],
488
+ // the fill's gradient, combined afterward into `fill`, `fillGradient`, `fillGradientAngle` and the other
489
+ // `fillGradient*` properties
490
+ [
491
+ "background-fill",
492
+ { property: "_backgroundFill", type: "enum", enums: ["solid", "linear-gradient", "radial-gradient"] },
493
+ ],
494
+ ["background-gradient-stop-colors", { property: "_backgroundStops", type: "text" }],
495
+ ["background-gradient-stop-positions", { property: "_backgroundPositions", type: "text" }],
496
+ ["background-gradient-direction", { property: "_backgroundDirection", type: "enum", enums: GRADIENT_DIRECTIONS }],
497
+ ...CYJS_FACE_PROPERTIES,
165
498
  ...LABEL,
166
499
  ]);
167
500
 
@@ -170,16 +503,69 @@ export const CYJS_EDGE_PROPERTIES: ReadonlyMap<string, CyjsPropertySpec> = new M
170
503
  ["line-color", { property: "color", type: "color" }],
171
504
  ["width", { property: "width", type: "nodeSize" }],
172
505
  ["line-style", { property: "lineStyle", type: "enum", enums: ["solid", "dotted", "dashed"] }],
506
+ // the dashes a dashed line is drawn with and their ends, which decide how it looks (`combineDashes`)
507
+ ["line-dash-pattern", { property: "_dashPattern", type: "text" }],
508
+ ["line-cap", { property: "_dashCap", type: "enum", enums: ["butt", "round", "square"] }],
509
+ // the line's own opacity, combined afterward into `opacity`, which the line is drawn at
510
+ ["line-opacity", { property: "_lineOpacity", type: "zeroOne" }],
511
+ ["line-outline-width", { property: "outlineWidth", type: "size" }],
512
+ ["line-fill", { property: "gradientKind", type: "enum", enums: ["solid", "linear-gradient", "radial-gradient"] }],
513
+ ["line-gradient-stop-colors", { property: "gradientColors", type: "text" }],
514
+ ["line-gradient-stop-positions", { property: "gradientStops", type: "text" }],
515
+ ["line-outline-color", { property: "outlineColor", type: "color" }],
516
+ ["underlay-color", { property: "underlayColor", type: "color" }],
517
+ ["underlay-opacity", { property: "underlayOpacity", type: "zeroOne" }],
518
+ ["underlay-padding", { property: "underlayPadding", type: "size" }],
519
+ ["overlay-color", { property: "overlayColor", type: "color" }],
520
+ ["overlay-opacity", { property: "overlayOpacity", type: "zeroOne" }],
521
+ ["overlay-padding", { property: "overlayPadding", type: "size" }],
173
522
  ["target-arrow-shape", { property: "targetArrow", type: "enum", enums: ARROWS }],
174
523
  ["source-arrow-shape", { property: "sourceArrow", type: "enum", enums: ARROWS }],
175
524
  ["target-arrow-color", { property: "targetArrowColor", type: "color" }],
176
525
  ["source-arrow-color", { property: "sourceArrowColor", type: "color" }],
526
+ ["mid-target-arrow-shape", { property: "midTargetArrow", type: "enum", enums: ARROWS }],
527
+ ["mid-source-arrow-shape", { property: "midSourceArrow", type: "enum", enums: ARROWS }],
528
+ ["mid-target-arrow-color", { property: "midTargetArrowColor", type: "color" }],
529
+ ["mid-source-arrow-color", { property: "midSourceArrowColor", type: "color" }],
530
+ // filled or hollow: combined with the shape afterward (`combineParts`), a hollow triangle being `triangle-open`
177
531
  ["target-arrow-fill", { property: "_targetArrowFill", type: "enum", enums: ["filled", "hollow"] }],
178
532
  ["source-arrow-fill", { property: "_sourceArrowFill", type: "enum", enums: ["filled", "hollow"] }],
179
- ["curve-style", { property: "curved", type: "enum", enums: CURVES }],
533
+ ["mid-target-arrow-fill", { property: "_midTargetArrowFill", type: "enum", enums: ["filled", "hollow"] }],
534
+ ["mid-source-arrow-fill", { property: "_midSourceArrowFill", type: "enum", enums: ["filled", "hollow"] }],
535
+ ["curve-style", { property: "curved", type: "enum", enums: CYJS_CURVE_STYLES }],
536
+ // a route's settings, read by the routes (`edgeRoutes`) as Cytoscape.js spells them
537
+ ["segment-distances", { property: "_segmentDistances", type: "text" }],
538
+ ["segment-weights", { property: "_segmentWeights", type: "text" }],
539
+ ["control-point-distances", { property: "_controlPointDistances", type: "text" }],
540
+ ["control-point-weights", { property: "_controlPointWeights", type: "text" }],
541
+ ["taxi-direction", { property: "_taxiDirection", type: "text" }],
542
+ ["taxi-turn", { property: "_taxiTurn", type: "text" }],
543
+ ["taxi-turn-min-distance", { property: "_taxiTurnMinDistance", type: "size" }],
544
+ ["edge-distances", { property: "_edgeDistances", type: "text" }],
545
+ ["loop-direction", { property: "_loopDirection", type: "text" }],
546
+ ["loop-sweep", { property: "_loopSweep", type: "text" }],
547
+ ["segment-radii", { property: "_segmentRadii", type: "text" }],
548
+ ["taxi-radius", { property: "_taxiRadius", type: "text" }],
549
+ ["radius-type", { property: "_radiusType", type: "text" }],
550
+ // where the ends meet the nodes, read with the routes (`edgePorts`)
551
+ ["source-endpoint", { property: "_sourceEndpoint", type: "text" }],
552
+ ["target-endpoint", { property: "_targetEndpoint", type: "text" }],
553
+ ["source-distance-from-node", { property: "sourceNodeGap", type: "size" }],
554
+ ["target-distance-from-node", { property: "targetNodeGap", type: "size" }],
555
+ // a bundle's control points are this far apart, so the curves' middles half of it (see cyjsNeutral)
556
+ ["control-point-step-size", { property: "fanSpacing", type: "size" }],
180
557
  ["arrow-scale", { property: "arrowSize", type: "positive" }],
181
558
  ["source-label", { property: "sourceLabel", type: "text" }],
182
559
  ["target-label", { property: "targetLabel", type: "text" }],
560
+ ["source-text-offset", { property: "sourceLabelOffset", type: "size" }],
561
+ ["target-text-offset", { property: "targetLabelOffset", type: "size" }],
562
+ ["source-text-margin-x", { property: "sourceLabelOffsetX", type: "signedSize" }],
563
+ ["source-text-margin-y", { property: "sourceLabelOffsetY", type: "signedSize" }],
564
+ ["target-text-margin-x", { property: "targetLabelOffsetX", type: "signedSize" }],
565
+ ["target-text-margin-y", { property: "targetLabelOffsetY", type: "signedSize" }],
566
+ // an angle, or autorotate along the line, which the routes work out (`autorotateLabels`)
567
+ ["source-text-rotation", { property: "_sourceRotation", type: "text" }],
568
+ ["target-text-rotation", { property: "_targetRotation", type: "text" }],
183
569
  ...LABEL,
184
570
  ]);
185
571
 
@@ -192,6 +578,33 @@ export function cyjsProperties(target: StyleTarget): ReadonlyMap<string, CyjsPro
192
578
  return target === "node" ? CYJS_NODE_PROPERTIES : CYJS_EDGE_PROPERTIES;
193
579
  }
194
580
 
581
+ /**
582
+ * Cytoscape.js 3.34.3's property aliases (`styfn.aliases`): each name is read as the property it points to.
583
+ */
584
+ const CYJS_ALIASES: ReadonlyMap<string, string> = new Map([
585
+ ["content", "label"],
586
+ ["control-point-distance", "control-point-distances"],
587
+ ["control-point-weight", "control-point-weights"],
588
+ ["segment-distance", "segment-distances"],
589
+ ["segment-weight", "segment-weights"],
590
+ ["segment-radius", "segment-radii"],
591
+ ["edge-text-rotation", "text-rotation"],
592
+ ["padding-left", "padding"],
593
+ ["padding-right", "padding"],
594
+ ["padding-top", "padding"],
595
+ ["padding-bottom", "padding"],
596
+ ]);
597
+
598
+ /**
599
+ * A dash-form property name with Cytoscape.js's aliases resolved (`content` is `label`, `segment-distance` is
600
+ * `segment-distances`, `padding-left` is `padding`).
601
+ * @param dashed - the name in dash form
602
+ * @returns the property it sets
603
+ */
604
+ export function cyjsAliasOf(dashed: string): string {
605
+ return CYJS_ALIASES.get(dashed) ?? dashed;
606
+ }
607
+
195
608
  /**
196
609
  * A property name in Cytoscape.js's dash form, aliases resolved (`backgroundColor` and `content` are read as
197
610
  * `background-color` and `label`).
@@ -199,8 +612,7 @@ export function cyjsProperties(target: StyleTarget): ReadonlyMap<string, CyjsPro
199
612
  * @returns the dash-form name
200
613
  */
201
614
  export function cyjsPropertyName(name: string): string {
202
- const dashed = name.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
203
- return dashed === "content" ? "label" : dashed;
615
+ return cyjsAliasOf(name.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`));
204
616
  }
205
617
 
206
618
  /** A parsed value, ready to draw. */
@@ -515,6 +927,7 @@ function parseFlat(spec: CyjsPropertySpec, raw: unknown, rendered = false): Flat
515
927
  return ok ? { kind: "number", value: x, units: null, str: String(x) } : null;
516
928
  }
517
929
  case "size":
930
+ case "signedSize":
518
931
  case "nodeSize":
519
932
  return parseSizeValue(spec, value, raw);
520
933
  case "text":
@@ -576,7 +989,9 @@ function parseSizeValue(spec: CyjsPropertySpec, value: unknown, raw: unknown): C
576
989
  if (Number.isNaN(x)) {
577
990
  return spec.type === "nodeSize" && raw === "label" ? { kind: "word", value: "label", str: "label" } : null;
578
991
  }
579
- return x < 0 ? null : { kind: "number", value: x, units, str: `${String(x)}${units ?? ""}` };
992
+ return x < 0 && spec.type !== "signedSize"
993
+ ? null
994
+ : { kind: "number", value: x, units, str: `${String(x)}${units ?? ""}` };
580
995
  }
581
996
 
582
997
  /**
@@ -690,7 +1105,11 @@ function parseMapData(spec: CyjsPropertySpec, value: string, mode: CyjsParseMode
690
1105
  return null;
691
1106
  }
692
1107
  const numeric =
693
- spec.type === "zeroOne" || spec.type === "positive" || spec.type === "size" || spec.type === "nodeSize";
1108
+ spec.type === "zeroOne" ||
1109
+ spec.type === "positive" ||
1110
+ spec.type === "size" ||
1111
+ spec.type === "signedSize" ||
1112
+ spec.type === "nodeSize";
694
1113
  if (spec.type !== "color" && !numeric) {
695
1114
  return null;
696
1115
  }
@@ -794,6 +1213,23 @@ export function applyCyjsMapper(
794
1213
  return null;
795
1214
  }
796
1215
 
1216
+ /**
1217
+ * A flat color as `#rrggbb`; a channel outside 0..255 is noted and undefined is returned.
1218
+ * @param v - the color
1219
+ * @param site - where it was read
1220
+ * @returns the color, or undefined
1221
+ */
1222
+ function colorNeutral(v: Extract<CyjsFlat, { kind: "color" }>, site: CanonSite): StyleValue | undefined {
1223
+ if (v.rgb.some((c) => !Number.isFinite(c) || c < 0 || c > 255)) {
1224
+ site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
1225
+ sample: v.str,
1226
+ element: site.element,
1227
+ });
1228
+ return undefined;
1229
+ }
1230
+ return `#${v.rgb.map((c) => Math.round(c).toString(16).padStart(2, "0")).join("")}`;
1231
+ }
1232
+
797
1233
  /**
798
1234
  * The neutral value a flat value is drawn as, for one property. A value Cytoscape.js draws from the page (an `em`
799
1235
  * size, a node sized to its label) cannot be evaluated: it is noted and undefined is returned.
@@ -804,25 +1240,12 @@ export function applyCyjsMapper(
804
1240
  */
805
1241
  export function cyjsNeutral(spec: CyjsPropertySpec, v: CyjsFlat, site: CanonSite): StyleValue | undefined {
806
1242
  switch (v.kind) {
807
- case "color": {
808
- if (v.rgb.some((c) => !Number.isFinite(c) || c < 0 || c > 255)) {
809
- site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
810
- sample: v.str,
811
- element: site.element,
812
- });
813
- return undefined;
814
- }
815
- return `#${v.rgb.map((c) => Math.round(c).toString(16).padStart(2, "0")).join("")}`;
816
- }
1243
+ case "color":
1244
+ return colorNeutral(v, site);
817
1245
  case "number":
818
- if (v.units === "em") {
819
- site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
820
- sample: v.str,
821
- element: site.element,
822
- });
823
- return undefined;
824
- }
825
- return num6(v.value);
1246
+ // Cytoscape.js steps a bundle's control points; a quadratic's middle is half as far out. It grows the
1247
+ // outline's path by its offset across, so the outline starts half the offset out (drawOutline).
1248
+ return num6((HALVED.has(spec.property) ? v.value / 2 : v.value) * (v.units === "em" ? EM_PX : 1));
826
1249
  default:
827
1250
  break;
828
1251
  }
@@ -830,25 +1253,58 @@ export function cyjsNeutral(spec: CyjsPropertySpec, v: CyjsFlat, site: CanonSite
830
1253
  switch (spec.property) {
831
1254
  case "width":
832
1255
  case "height":
833
- site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, { sample: v.str, element: site.element });
1256
+ // a node sized to its label is drawn so by the node sizes (`nodeSizes`); an edge has no such width
1257
+ if (site.target === "edge") {
1258
+ site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
1259
+ sample: v.str,
1260
+ element: site.element,
1261
+ });
1262
+ }
834
1263
  return undefined;
835
1264
  case "label":
836
1265
  case "sourceLabel":
837
1266
  case "targetLabel":
838
1267
  case "labelFont":
839
1268
  return String(word);
1269
+ case "gradientKind":
1270
+ return GRADIENT_KINDS.get(String(word)) ?? undefined;
1271
+ case "gradientColors":
1272
+ return gradientColors(String(word), site);
1273
+ case "gradientStops":
1274
+ return gradientStops(String(word));
840
1275
  case "labelItalic":
841
1276
  return word === "italic" || word === "oblique";
842
1277
  case "curved":
843
1278
  return !STRAIGHT.has(String(word));
844
- case "shape":
1279
+ case "shapePoints":
1280
+ return cyjsPointsToNeutral(String(word)) ?? undefined;
1281
+ case "underlayShape":
1282
+ case "overlayShape":
845
1283
  return canonEnum("shape", String(word), "cytoscape-js", site) ?? undefined;
1284
+ case "shape": {
1285
+ const polygon = String(word).toLowerCase();
1286
+ if (polygon === "polygon") {
1287
+ return "polygon";
1288
+ }
1289
+ // drawn exactly as the polygon Cytoscape.js builds, by `cyjsPolygonShapes`
1290
+ return CYJS_POLYGON_SHAPES.has(polygon) || CYJS_ROUND_SHAPES.has(polygon)
1291
+ ? `other:${polygon}`
1292
+ : (canonEnum("shape", String(word), "cytoscape-js", site) ?? undefined);
1293
+ }
846
1294
  case "borderStyle":
847
1295
  return canonEnum("borderStyle", String(word), "cytoscape-js", site) ?? undefined;
1296
+ case "outerBorderStyle":
1297
+ // cytoscape.js 3.34.3 drawOutline strokes a double outline whole and then erases a line a third of the
1298
+ // BORDER's width down its middle, a hairline under a border of 1: the ring it shows is solid
1299
+ return word === "double"
1300
+ ? "solid"
1301
+ : (canonEnum("borderStyle", String(word), "cytoscape-js", site) ?? undefined);
848
1302
  case "lineStyle":
849
1303
  return canonEnum("lineStyle", String(word), "cytoscape-js", site) ?? undefined;
850
1304
  case "sourceArrow":
851
1305
  case "targetArrow":
1306
+ case "midSourceArrow":
1307
+ case "midTargetArrow":
852
1308
  return canonEnum("arrow", String(word), "cytoscape-js", site) ?? undefined;
853
1309
  case "labelWeight":
854
1310
  return canonEnum("weight", String(word), "cytoscape-js", site) ?? undefined;
@@ -882,3 +1338,26 @@ export function cyjsRendered(
882
1338
  }
883
1339
  return cyjsNeutral(spec, v, site);
884
1340
  }
1341
+
1342
+ /**
1343
+ * The line class a dash array looks like against the line's width: solid where its gaps are a tenth of it or less,
1344
+ * dotted where no dash is longer than one and a half widths, dash-dot where a dash is twice another, else dashed.
1345
+ * @param dash - the dashes and gaps, in pixels
1346
+ * @param width - the line's width
1347
+ * @param cap - the dashes' ends
1348
+ * @returns the neutral line style
1349
+ */
1350
+ export function cyjsDashLook(dash: readonly number[], width: number, cap: string): string {
1351
+ const pairs = dash.length % 2 === 1 ? [...dash, ...dash] : [...dash];
1352
+ const grow = cap === "butt" ? 0 : width;
1353
+ const on = pairs.filter((_, i) => i % 2 === 0).map((d) => Math.max(0, d) + grow);
1354
+ const off = pairs.filter((_, i) => i % 2 === 1).map((d) => Math.max(0, d - grow));
1355
+ const sum = (xs: readonly number[]): number => xs.reduce((a, b) => a + b, 0);
1356
+ if (sum(off) <= 0.1 * (sum(on) + sum(off))) {
1357
+ return "solid";
1358
+ }
1359
+ if (on.every((d) => d <= Math.max(1, width) * 1.5)) {
1360
+ return "dotted";
1361
+ }
1362
+ return Math.max(...on) >= 2 * Math.min(...on) ? "dash-dot" : "dashed";
1363
+ }