@graphty/graph-io 0.3.47 → 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 (770) hide show
  1. package/dist/chunks/{approximations-wWjCRzKj.js → approximations-Bzn3L-je.js} +2 -2
  2. package/dist/chunks/{approximations-wWjCRzKj.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-DiGq58c3.js → block-iptrlMBb.js} +947 -134
  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-BE2xir2k.js +157 -0
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-BKwqelYD.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-BKwqelYD.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/context-C3p0RQxR.js +664 -0
  14. package/dist/chunks/context-C3p0RQxR.js.map +1 -0
  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-DXHx7nwR.js +349 -0
  18. package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
  19. package/dist/chunks/cx-export-Bt6NoqTQ.js +259 -0
  20. package/dist/chunks/cx-export-Bt6NoqTQ.js.map +1 -0
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/descriptor-C-YDhtsn.js +48 -0
  24. package/dist/chunks/descriptor-C-YDhtsn.js.map +1 -0
  25. package/dist/chunks/descriptor-DLA5kINx.js +142 -0
  26. package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
  27. package/dist/chunks/{emit-CwU8cUmG.js → emit-BwHQkZle.js} +1690 -103
  28. package/dist/chunks/emit-BwHQkZle.js.map +1 -0
  29. package/dist/chunks/{escape-CgzxiYPg.js → escape-CuCIzNMB.js} +12 -12
  30. package/dist/chunks/{escape-CgzxiYPg.js.map → escape-CuCIzNMB.js.map} +1 -1
  31. package/dist/chunks/{export-BvqAXCKh.js → export-Cha4dRFz.js} +48 -1780
  32. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  33. package/dist/chunks/{exporter--Mk9gXCJ.js → exporter-BP6otMO6.js} +6 -4
  34. package/dist/chunks/{exporter--Mk9gXCJ.js.map → exporter-BP6otMO6.js.map} +1 -1
  35. package/dist/chunks/{exporter-CrDWIyiq.js → exporter-D2CETOMK.js} +1222 -154
  36. package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
  37. package/dist/chunks/{exporter-DndFlGSa.js → exporter-D9yMtocA.js} +7 -6
  38. package/dist/chunks/{exporter-DndFlGSa.js.map → exporter-D9yMtocA.js.map} +1 -1
  39. package/dist/chunks/exporter-_jrBTnos.js +1009 -0
  40. package/dist/chunks/exporter-_jrBTnos.js.map +1 -0
  41. package/dist/chunks/{exporter-CJgfhF-l.js → exporter-nDfxIK5D.js} +9 -7
  42. package/dist/chunks/{exporter-CJgfhF-l.js.map → exporter-nDfxIK5D.js.map} +1 -1
  43. package/dist/chunks/format-BXiAb-1h.js +408 -0
  44. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  45. package/dist/chunks/{generic-Dq1ntt9q.js → generic-ymWCETAJ.js} +387 -31
  46. package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
  47. package/dist/chunks/{importer-CMmeMWlC.js → importer-B92x1xY5.js} +15 -263
  48. package/dist/chunks/importer-B92x1xY5.js.map +1 -0
  49. package/dist/chunks/{importer-DiZRmOQG.js → importer-CT9mJ1nn.js} +328 -90
  50. package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
  51. package/dist/chunks/{importer-COTK9Tsl.js → importer-DaLTjbds.js} +116 -1099
  52. package/dist/chunks/importer-DaLTjbds.js.map +1 -0
  53. package/dist/chunks/{importer-iFYPEKaJ.js → importer-GREKMdIf.js} +28 -16
  54. package/dist/chunks/importer-GREKMdIf.js.map +1 -0
  55. package/dist/chunks/{importer-BSvfrX_h.js → importer-PqaaKKnY.js} +23 -1016
  56. package/dist/chunks/importer-PqaaKKnY.js.map +1 -0
  57. package/dist/chunks/{importer-yh_aBCU6.js → importer-Vn5QvmmJ.js} +66 -12
  58. package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
  59. package/dist/chunks/{importer-e6LGpqHB.js → importer-vRq4h3j5.js} +1470 -354
  60. package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
  61. package/dist/chunks/input-CAxt_aV-.js +1397 -0
  62. package/dist/chunks/input-CAxt_aV-.js.map +1 -0
  63. package/dist/chunks/{json-elements-DJZRZ6jd.js → json-elements-Cq76WjnZ.js} +4 -4
  64. package/dist/chunks/{json-elements-DJZRZ6jd.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  65. package/dist/chunks/{lexicon-CT69Kd87.js → lexicon-Clf4QIyl.js} +299 -77
  66. package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
  67. package/dist/chunks/{ontology-export-G4MqRdux.js → ontology-export-OMo91mb0.js} +4 -3
  68. package/dist/chunks/{ontology-export-G4MqRdux.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  69. package/dist/chunks/{records-CiaWZrFH.js → records-NJiYvekn.js} +2 -2
  70. package/dist/chunks/{records-CiaWZrFH.js.map → records-NJiYvekn.js.map} +1 -1
  71. package/dist/chunks/{format-BpQBx8MZ.js → report-CwMfYa9J.js} +70 -127
  72. package/dist/chunks/report-CwMfYa9J.js.map +1 -0
  73. package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
  74. package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
  75. package/dist/chunks/sigv4-EokFic1V.js +247 -0
  76. package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
  77. package/dist/chunks/{styles-BQnsga7p.js → styles-CCs214_3.js} +1300 -168
  78. package/dist/chunks/styles-CCs214_3.js.map +1 -0
  79. package/dist/chunks/styles-Cm62yyQX.js +2812 -0
  80. package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
  81. package/dist/chunks/styles-DPQQIig4.js +1928 -0
  82. package/dist/chunks/styles-DPQQIig4.js.map +1 -0
  83. package/dist/chunks/styles-yed-UMFdNqze.js +1213 -0
  84. package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
  85. package/dist/chunks/{text-CzJNFOS9.js → text-ystE2bYi.js} +2 -2
  86. package/dist/chunks/{text-CzJNFOS9.js.map → text-ystE2bYi.js.map} +1 -1
  87. package/dist/csv.js +7 -5
  88. package/dist/csv.js.map +1 -1
  89. package/dist/cx.js +5 -4
  90. package/dist/cx.js.map +1 -1
  91. package/dist/cx2.js +2 -2
  92. package/dist/cys.js +1 -1
  93. package/dist/dot.js +5 -4
  94. package/dist/dot.js.map +1 -1
  95. package/dist/gexf.js +42 -10
  96. package/dist/gexf.js.map +1 -1
  97. package/dist/gml.js +850 -193
  98. package/dist/gml.js.map +1 -1
  99. package/dist/graph-io.js +1189 -220
  100. package/dist/graph-io.js.map +1 -1
  101. package/dist/graphml.js +3 -3
  102. package/dist/json.js +3 -2
  103. package/dist/neo4j.js +6 -4
  104. package/dist/neo4j.js.map +1 -1
  105. package/dist/obo.js +1 -1
  106. package/dist/pajek.js +1 -1
  107. package/dist/positions.js +45 -3
  108. package/dist/positions.js.map +1 -1
  109. package/dist/sources-cypher.d.ts +1 -0
  110. package/dist/sources-cypher.js +1351 -0
  111. package/dist/sources-cypher.js.map +1 -0
  112. package/dist/sources-ndex.d.ts +1 -0
  113. package/dist/sources-ndex.js +278 -0
  114. package/dist/sources-ndex.js.map +1 -0
  115. package/dist/sources-rest.d.ts +1 -0
  116. package/dist/sources-rest.js +1377 -0
  117. package/dist/sources-rest.js.map +1 -0
  118. package/dist/sources-sparql.d.ts +1 -0
  119. package/dist/sources-sparql.js +405 -0
  120. package/dist/sources-sparql.js.map +1 -0
  121. package/dist/src/common/report.d.ts +6 -3
  122. package/dist/src/common/report.d.ts.map +1 -1
  123. package/dist/src/common/report.js +15 -9
  124. package/dist/src/common/report.js.map +1 -1
  125. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cx/importer.js +5 -1
  127. package/dist/src/formats/cx/importer.js.map +1 -1
  128. package/dist/src/formats/cx/styles.d.ts +24 -1
  129. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cx/styles.js +118 -11
  131. package/dist/src/formats/cx/styles.js.map +1 -1
  132. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  133. package/dist/src/formats/cx2/importer.js +1 -0
  134. package/dist/src/formats/cx2/importer.js.map +1 -1
  135. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  136. package/dist/src/formats/cx2/styles.js +3 -1
  137. package/dist/src/formats/cx2/styles.js.map +1 -1
  138. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  139. package/dist/src/formats/cys/importer.js +1 -0
  140. package/dist/src/formats/cys/importer.js.map +1 -1
  141. package/dist/src/formats/cys/styles.d.ts +2 -0
  142. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  143. package/dist/src/formats/cys/styles.js +15 -7
  144. package/dist/src/formats/cys/styles.js.map +1 -1
  145. package/dist/src/formats/dot/drawing.d.ts +98 -0
  146. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  147. package/dist/src/formats/dot/drawing.js +734 -0
  148. package/dist/src/formats/dot/drawing.js.map +1 -0
  149. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  150. package/dist/src/formats/dot/importer.js +108 -31
  151. package/dist/src/formats/dot/importer.js.map +1 -1
  152. package/dist/src/formats/dot/label-places.d.ts +34 -0
  153. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  154. package/dist/src/formats/dot/label-places.js +179 -0
  155. package/dist/src/formats/dot/label-places.js.map +1 -0
  156. package/dist/src/formats/dot/record.d.ts +50 -0
  157. package/dist/src/formats/dot/record.d.ts.map +1 -0
  158. package/dist/src/formats/dot/record.js +275 -0
  159. package/dist/src/formats/dot/record.js.map +1 -0
  160. package/dist/src/formats/dot/styles.d.ts +62 -2
  161. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  162. package/dist/src/formats/dot/styles.js +1457 -120
  163. package/dist/src/formats/dot/styles.js.map +1 -1
  164. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  165. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  166. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  167. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  168. package/dist/src/formats/gexf/importer.d.ts +7 -0
  169. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  170. package/dist/src/formats/gexf/importer.js +41 -5
  171. package/dist/src/formats/gexf/importer.js.map +1 -1
  172. package/dist/src/formats/gexf/preview.d.ts +77 -0
  173. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  174. package/dist/src/formats/gexf/preview.js +191 -0
  175. package/dist/src/formats/gexf/preview.js.map +1 -0
  176. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  177. package/dist/src/formats/gexf/schema.js +2 -1
  178. package/dist/src/formats/gexf/schema.js.map +1 -1
  179. package/dist/src/formats/gexf/styles.d.ts +60 -16
  180. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  181. package/dist/src/formats/gexf/styles.js +883 -131
  182. package/dist/src/formats/gexf/styles.js.map +1 -1
  183. package/dist/src/formats/gml/importer.d.ts +5 -2
  184. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  185. package/dist/src/formats/gml/importer.js +258 -71
  186. package/dist/src/formats/gml/importer.js.map +1 -1
  187. package/dist/src/formats/gml/index.d.ts +1 -1
  188. package/dist/src/formats/gml/index.d.ts.map +1 -1
  189. package/dist/src/formats/gml/index.js +1 -1
  190. package/dist/src/formats/gml/index.js.map +1 -1
  191. package/dist/src/formats/gml/positions.d.ts +7 -0
  192. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  193. package/dist/src/formats/gml/positions.js +29 -7
  194. package/dist/src/formats/gml/positions.js.map +1 -1
  195. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  196. package/dist/src/formats/gml/styles.js +756 -103
  197. package/dist/src/formats/gml/styles.js.map +1 -1
  198. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  199. package/dist/src/formats/graphml/styles-plain.js +8 -12
  200. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  201. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  202. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  203. package/dist/src/formats/graphml/styles-yed.js +749 -148
  204. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  205. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  206. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  207. package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
  208. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  209. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  210. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  211. package/dist/src/formats/graphml/yfiles.js +16 -6
  212. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  213. package/dist/src/formats/json/dialect.d.ts +3 -2
  214. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  215. package/dist/src/formats/json/dialect.js +39 -5
  216. package/dist/src/formats/json/dialect.js.map +1 -1
  217. package/dist/src/formats/json/importer.d.ts +13 -2
  218. package/dist/src/formats/json/importer.d.ts.map +1 -1
  219. package/dist/src/formats/json/importer.js +42 -6
  220. package/dist/src/formats/json/importer.js.map +1 -1
  221. package/dist/src/formats/json/index.d.ts +1 -1
  222. package/dist/src/formats/json/index.d.ts.map +1 -1
  223. package/dist/src/formats/json/index.js +1 -1
  224. package/dist/src/formats/json/index.js.map +1 -1
  225. package/dist/src/formats/json/positions.d.ts +5 -2
  226. package/dist/src/formats/json/positions.d.ts.map +1 -1
  227. package/dist/src/formats/json/positions.js +20 -4
  228. package/dist/src/formats/json/positions.js.map +1 -1
  229. package/dist/src/formats/json/styles.d.ts +12 -1
  230. package/dist/src/formats/json/styles.d.ts.map +1 -1
  231. package/dist/src/formats/json/styles.js +1755 -136
  232. package/dist/src/formats/json/styles.js.map +1 -1
  233. package/dist/src/formats/pajek/draw.d.ts +96 -0
  234. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  235. package/dist/src/formats/pajek/draw.js +372 -0
  236. package/dist/src/formats/pajek/draw.js.map +1 -0
  237. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  238. package/dist/src/formats/pajek/exporter.js +70 -51
  239. package/dist/src/formats/pajek/exporter.js.map +1 -1
  240. package/dist/src/formats/pajek/importer.d.ts +9 -0
  241. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  242. package/dist/src/formats/pajek/importer.js +233 -102
  243. package/dist/src/formats/pajek/importer.js.map +1 -1
  244. package/dist/src/formats/pajek/index.d.ts +1 -0
  245. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  246. package/dist/src/formats/pajek/index.js.map +1 -1
  247. package/dist/src/formats/pajek/styles.d.ts +15 -7
  248. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  249. package/dist/src/formats/pajek/styles.js +1279 -114
  250. package/dist/src/formats/pajek/styles.js.map +1 -1
  251. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  252. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  253. package/dist/src/formats/pajek/syntax.js +26 -2
  254. package/dist/src/formats/pajek/syntax.js.map +1 -1
  255. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  256. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  257. package/dist/src/formats/xgmml/emit.js +65 -5
  258. package/dist/src/formats/xgmml/emit.js.map +1 -1
  259. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  260. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  261. package/dist/src/formats/xgmml/styles.js +278 -60
  262. package/dist/src/formats/xgmml/styles.js.map +1 -1
  263. package/dist/src/index.d.ts +10 -2
  264. package/dist/src/index.d.ts.map +1 -1
  265. package/dist/src/index.js +11 -2
  266. package/dist/src/index.js.map +1 -1
  267. package/dist/src/positions/convert.d.ts.map +1 -1
  268. package/dist/src/positions/convert.js +11 -1
  269. package/dist/src/positions/convert.js.map +1 -1
  270. package/dist/src/positions/extract.d.ts.map +1 -1
  271. package/dist/src/positions/extract.js +53 -1
  272. package/dist/src/positions/extract.js.map +1 -1
  273. package/dist/src/positions/index.d.ts +1 -1
  274. package/dist/src/positions/index.d.ts.map +1 -1
  275. package/dist/src/positions/types.d.ts +59 -0
  276. package/dist/src/positions/types.d.ts.map +1 -1
  277. package/dist/src/registry.d.ts +173 -1
  278. package/dist/src/registry.d.ts.map +1 -1
  279. package/dist/src/registry.js +196 -1
  280. package/dist/src/registry.js.map +1 -1
  281. package/dist/src/sources/builtins.d.ts +11 -0
  282. package/dist/src/sources/builtins.d.ts.map +1 -0
  283. package/dist/src/sources/builtins.js +53 -0
  284. package/dist/src/sources/builtins.js.map +1 -0
  285. package/dist/src/sources/codes.d.ts +230 -0
  286. package/dist/src/sources/codes.d.ts.map +1 -0
  287. package/dist/src/sources/codes.js +58 -0
  288. package/dist/src/sources/codes.js.map +1 -0
  289. package/dist/src/sources/context.d.ts +112 -0
  290. package/dist/src/sources/context.d.ts.map +1 -0
  291. package/dist/src/sources/context.js +740 -0
  292. package/dist/src/sources/context.js.map +1 -0
  293. package/dist/src/sources/credentials.d.ts +179 -0
  294. package/dist/src/sources/credentials.d.ts.map +1 -0
  295. package/dist/src/sources/credentials.js +301 -0
  296. package/dist/src/sources/credentials.js.map +1 -0
  297. package/dist/src/sources/cypher/descriptor.d.ts +21 -0
  298. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -0
  299. package/dist/src/sources/cypher/descriptor.js +124 -0
  300. package/dist/src/sources/cypher/descriptor.js.map +1 -0
  301. package/dist/src/sources/cypher/flatten.d.ts +72 -0
  302. package/dist/src/sources/cypher/flatten.d.ts.map +1 -0
  303. package/dist/src/sources/cypher/flatten.js +279 -0
  304. package/dist/src/sources/cypher/flatten.js.map +1 -0
  305. package/dist/src/sources/cypher/index.d.ts +33 -0
  306. package/dist/src/sources/cypher/index.d.ts.map +1 -0
  307. package/dist/src/sources/cypher/index.js +511 -0
  308. package/dist/src/sources/cypher/index.js.map +1 -0
  309. package/dist/src/sources/cypher/params.d.ts +40 -0
  310. package/dist/src/sources/cypher/params.d.ts.map +1 -0
  311. package/dist/src/sources/cypher/params.js +6 -0
  312. package/dist/src/sources/cypher/params.js.map +1 -0
  313. package/dist/src/sources/cypher/profiles.d.ts +44 -0
  314. package/dist/src/sources/cypher/profiles.d.ts.map +1 -0
  315. package/dist/src/sources/cypher/profiles.js +61 -0
  316. package/dist/src/sources/cypher/profiles.js.map +1 -0
  317. package/dist/src/sources/cypher/query-builder.d.ts +123 -0
  318. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -0
  319. package/dist/src/sources/cypher/query-builder.js +267 -0
  320. package/dist/src/sources/cypher/query-builder.js.map +1 -0
  321. package/dist/src/sources/cypher/transports/bolt.d.ts +21 -0
  322. package/dist/src/sources/cypher/transports/bolt.d.ts.map +1 -0
  323. package/dist/src/sources/cypher/transports/bolt.js +185 -0
  324. package/dist/src/sources/cypher/transports/bolt.js.map +1 -0
  325. package/dist/src/sources/cypher/transports/neptune-analytics.d.ts +15 -0
  326. package/dist/src/sources/cypher/transports/neptune-analytics.d.ts.map +1 -0
  327. package/dist/src/sources/cypher/transports/neptune-analytics.js +38 -0
  328. package/dist/src/sources/cypher/transports/neptune-analytics.js.map +1 -0
  329. package/dist/src/sources/cypher/transports/neptune-https.d.ts +31 -0
  330. package/dist/src/sources/cypher/transports/neptune-https.d.ts.map +1 -0
  331. package/dist/src/sources/cypher/transports/neptune-https.js +104 -0
  332. package/dist/src/sources/cypher/transports/neptune-https.js.map +1 -0
  333. package/dist/src/sources/cypher/transports/query-api.d.ts +14 -0
  334. package/dist/src/sources/cypher/transports/query-api.d.ts.map +1 -0
  335. package/dist/src/sources/cypher/transports/query-api.js +80 -0
  336. package/dist/src/sources/cypher/transports/query-api.js.map +1 -0
  337. package/dist/src/sources/cypher/transports/transport.d.ts +78 -0
  338. package/dist/src/sources/cypher/transports/transport.d.ts.map +1 -0
  339. package/dist/src/sources/cypher/transports/transport.js +77 -0
  340. package/dist/src/sources/cypher/transports/transport.js.map +1 -0
  341. package/dist/src/sources/cypher/types-map.d.ts +91 -0
  342. package/dist/src/sources/cypher/types-map.d.ts.map +1 -0
  343. package/dist/src/sources/cypher/types-map.js +306 -0
  344. package/dist/src/sources/cypher/types-map.js.map +1 -0
  345. package/dist/src/sources/define.d.ts +47 -0
  346. package/dist/src/sources/define.d.ts.map +1 -0
  347. package/dist/src/sources/define.js +173 -0
  348. package/dist/src/sources/define.js.map +1 -0
  349. package/dist/src/sources/fail.d.ts +33 -0
  350. package/dist/src/sources/fail.d.ts.map +1 -0
  351. package/dist/src/sources/fail.js +49 -0
  352. package/dist/src/sources/fail.js.map +1 -0
  353. package/dist/src/sources/ids.d.ts +69 -0
  354. package/dist/src/sources/ids.d.ts.map +1 -0
  355. package/dist/src/sources/ids.js +69 -0
  356. package/dist/src/sources/ids.js.map +1 -0
  357. package/dist/src/sources/ndex/client.d.ts +31 -0
  358. package/dist/src/sources/ndex/client.d.ts.map +1 -0
  359. package/dist/src/sources/ndex/client.js +90 -0
  360. package/dist/src/sources/ndex/client.js.map +1 -0
  361. package/dist/src/sources/ndex/descriptor.d.ts +10 -0
  362. package/dist/src/sources/ndex/descriptor.d.ts.map +1 -0
  363. package/dist/src/sources/ndex/descriptor.js +55 -0
  364. package/dist/src/sources/ndex/descriptor.js.map +1 -0
  365. package/dist/src/sources/ndex/expand.d.ts +20 -0
  366. package/dist/src/sources/ndex/expand.d.ts.map +1 -0
  367. package/dist/src/sources/ndex/expand.js +87 -0
  368. package/dist/src/sources/ndex/expand.js.map +1 -0
  369. package/dist/src/sources/ndex/index.d.ts +25 -0
  370. package/dist/src/sources/ndex/index.d.ts.map +1 -0
  371. package/dist/src/sources/ndex/index.js +191 -0
  372. package/dist/src/sources/ndex/index.js.map +1 -0
  373. package/dist/src/sources/ndex/params.d.ts +17 -0
  374. package/dist/src/sources/ndex/params.d.ts.map +1 -0
  375. package/dist/src/sources/ndex/params.js +6 -0
  376. package/dist/src/sources/ndex/params.js.map +1 -0
  377. package/dist/src/sources/ndex/share-url.d.ts +40 -0
  378. package/dist/src/sources/ndex/share-url.d.ts.map +1 -0
  379. package/dist/src/sources/ndex/share-url.js +64 -0
  380. package/dist/src/sources/ndex/share-url.js.map +1 -0
  381. package/dist/src/sources/params.d.ts +31 -0
  382. package/dist/src/sources/params.d.ts.map +1 -0
  383. package/dist/src/sources/params.js +6 -0
  384. package/dist/src/sources/params.js.map +1 -0
  385. package/dist/src/sources/registry.d.ts +118 -0
  386. package/dist/src/sources/registry.d.ts.map +1 -0
  387. package/dist/src/sources/registry.js +193 -0
  388. package/dist/src/sources/registry.js.map +1 -0
  389. package/dist/src/sources/rest/descriptor.d.ts +16 -0
  390. package/dist/src/sources/rest/descriptor.d.ts.map +1 -0
  391. package/dist/src/sources/rest/descriptor.js +76 -0
  392. package/dist/src/sources/rest/descriptor.js.map +1 -0
  393. package/dist/src/sources/rest/index.d.ts +14 -0
  394. package/dist/src/sources/rest/index.d.ts.map +1 -0
  395. package/dist/src/sources/rest/index.js +13 -0
  396. package/dist/src/sources/rest/index.js.map +1 -0
  397. package/dist/src/sources/rest/mapping.d.ts +30 -0
  398. package/dist/src/sources/rest/mapping.d.ts.map +1 -0
  399. package/dist/src/sources/rest/mapping.js +362 -0
  400. package/dist/src/sources/rest/mapping.js.map +1 -0
  401. package/dist/src/sources/rest/openalex.d.ts +27 -0
  402. package/dist/src/sources/rest/openalex.d.ts.map +1 -0
  403. package/dist/src/sources/rest/openalex.js +269 -0
  404. package/dist/src/sources/rest/openalex.js.map +1 -0
  405. package/dist/src/sources/rest/paging.d.ts +53 -0
  406. package/dist/src/sources/rest/paging.d.ts.map +1 -0
  407. package/dist/src/sources/rest/paging.js +138 -0
  408. package/dist/src/sources/rest/paging.js.map +1 -0
  409. package/dist/src/sources/rest/params.d.ts +216 -0
  410. package/dist/src/sources/rest/params.d.ts.map +1 -0
  411. package/dist/src/sources/rest/params.js +7 -0
  412. package/dist/src/sources/rest/params.js.map +1 -0
  413. package/dist/src/sources/rest/records.d.ts +41 -0
  414. package/dist/src/sources/rest/records.d.ts.map +1 -0
  415. package/dist/src/sources/rest/records.js +240 -0
  416. package/dist/src/sources/rest/records.js.map +1 -0
  417. package/dist/src/sources/rest/samples/deps-dev.d.ts +10 -0
  418. package/dist/src/sources/rest/samples/deps-dev.d.ts.map +1 -0
  419. package/dist/src/sources/rest/samples/deps-dev.js +47 -0
  420. package/dist/src/sources/rest/samples/deps-dev.js.map +1 -0
  421. package/dist/src/sources/rest/samples/string.d.ts +9 -0
  422. package/dist/src/sources/rest/samples/string.d.ts.map +1 -0
  423. package/dist/src/sources/rest/samples/string.js +42 -0
  424. package/dist/src/sources/rest/samples/string.js.map +1 -0
  425. package/dist/src/sources/rest/selectors.d.ts +41 -0
  426. package/dist/src/sources/rest/selectors.d.ts.map +1 -0
  427. package/dist/src/sources/rest/selectors.js +81 -0
  428. package/dist/src/sources/rest/selectors.js.map +1 -0
  429. package/dist/src/sources/rest/source.d.ts +67 -0
  430. package/dist/src/sources/rest/source.d.ts.map +1 -0
  431. package/dist/src/sources/rest/source.js +650 -0
  432. package/dist/src/sources/rest/source.js.map +1 -0
  433. package/dist/src/sources/rest/templates.d.ts +38 -0
  434. package/dist/src/sources/rest/templates.d.ts.map +1 -0
  435. package/dist/src/sources/rest/templates.js +125 -0
  436. package/dist/src/sources/rest/templates.js.map +1 -0
  437. package/dist/src/sources/run.d.ts +93 -0
  438. package/dist/src/sources/run.d.ts.map +1 -0
  439. package/dist/src/sources/run.js +673 -0
  440. package/dist/src/sources/run.js.map +1 -0
  441. package/dist/src/sources/sha256.d.ts +12 -0
  442. package/dist/src/sources/sha256.d.ts.map +1 -0
  443. package/dist/src/sources/sha256.js +95 -0
  444. package/dist/src/sources/sha256.js.map +1 -0
  445. package/dist/src/sources/sigv4.d.ts +26 -0
  446. package/dist/src/sources/sigv4.d.ts.map +1 -0
  447. package/dist/src/sources/sigv4.js +184 -0
  448. package/dist/src/sources/sigv4.js.map +1 -0
  449. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  450. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  451. package/dist/src/sources/sparql/descriptor.js +64 -0
  452. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  453. package/dist/src/sources/sparql/index.d.ts +28 -0
  454. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  455. package/dist/src/sources/sparql/index.js +314 -0
  456. package/dist/src/sources/sparql/index.js.map +1 -0
  457. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  458. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  459. package/dist/src/sources/sparql/ntriples.js +180 -0
  460. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  461. package/dist/src/sources/sparql/params.d.ts +27 -0
  462. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  463. package/dist/src/sources/sparql/params.js +5 -0
  464. package/dist/src/sources/sparql/params.js.map +1 -0
  465. package/dist/src/sources/sparql/query.d.ts +72 -0
  466. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  467. package/dist/src/sources/sparql/query.js +113 -0
  468. package/dist/src/sources/sparql/query.js.map +1 -0
  469. package/dist/src/sources/testing.d.ts +96 -0
  470. package/dist/src/sources/testing.d.ts.map +1 -0
  471. package/dist/src/sources/testing.js +138 -0
  472. package/dist/src/sources/testing.js.map +1 -0
  473. package/dist/src/sources/types.d.ts +696 -0
  474. package/dist/src/sources/types.d.ts.map +1 -0
  475. package/dist/src/sources/types.js +10 -0
  476. package/dist/src/sources/types.js.map +1 -0
  477. package/dist/src/styles/annotations.d.ts +61 -5
  478. package/dist/src/styles/annotations.d.ts.map +1 -1
  479. package/dist/src/styles/annotations.js +130 -22
  480. package/dist/src/styles/annotations.js.map +1 -1
  481. package/dist/src/styles/canon/bends.d.ts +46 -0
  482. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  483. package/dist/src/styles/canon/bends.js +123 -0
  484. package/dist/src/styles/canon/bends.js.map +1 -1
  485. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  486. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  487. package/dist/src/styles/canon/color-tables.js +10 -4
  488. package/dist/src/styles/canon/color-tables.js.map +1 -1
  489. package/dist/src/styles/canon/color.d.ts +3 -1
  490. package/dist/src/styles/canon/color.d.ts.map +1 -1
  491. package/dist/src/styles/canon/color.js +103 -3
  492. package/dist/src/styles/canon/color.js.map +1 -1
  493. package/dist/src/styles/canon/enums.d.ts +2 -2
  494. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  495. package/dist/src/styles/canon/enums.js +82 -7
  496. package/dist/src/styles/canon/enums.js.map +1 -1
  497. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  498. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  499. package/dist/src/styles/canon/graphviz.js +57 -9
  500. package/dist/src/styles/canon/graphviz.js.map +1 -1
  501. package/dist/src/styles/canon/number.d.ts +8 -0
  502. package/dist/src/styles/canon/number.d.ts.map +1 -1
  503. package/dist/src/styles/canon/number.js +18 -0
  504. package/dist/src/styles/canon/number.js.map +1 -1
  505. package/dist/src/styles/canon/text.d.ts +29 -2
  506. package/dist/src/styles/canon/text.d.ts.map +1 -1
  507. package/dist/src/styles/canon/text.js +156 -16
  508. package/dist/src/styles/canon/text.js.map +1 -1
  509. package/dist/src/styles/codes.d.ts +2 -0
  510. package/dist/src/styles/codes.d.ts.map +1 -1
  511. package/dist/src/styles/codes.js +2 -0
  512. package/dist/src/styles/codes.js.map +1 -1
  513. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  514. package/dist/src/styles/cyjs/cascade.js +1037 -35
  515. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  516. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  517. package/dist/src/styles/cyjs/defaults-table.js +5 -0
  518. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  519. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  520. package/dist/src/styles/cyjs/emit.js +216 -12
  521. package/dist/src/styles/cyjs/emit.js.map +1 -1
  522. package/dist/src/styles/cyjs/face.d.ts +20 -0
  523. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  524. package/dist/src/styles/cyjs/face.js +332 -0
  525. package/dist/src/styles/cyjs/face.js.map +1 -0
  526. package/dist/src/styles/cyjs/mappers.d.ts +48 -2
  527. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  528. package/dist/src/styles/cyjs/mappers.js +463 -26
  529. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  530. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  531. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  532. package/dist/src/styles/cyjs/routes.js +360 -0
  533. package/dist/src/styles/cyjs/routes.js.map +1 -0
  534. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  535. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  536. package/dist/src/styles/cytoscape/charts.js +560 -0
  537. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  538. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  539. package/dist/src/styles/cytoscape/emit.js +204 -44
  540. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  541. package/dist/src/styles/cytoscape/lexicon.d.ts +97 -3
  542. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  543. package/dist/src/styles/cytoscape/lexicon.js +413 -79
  544. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  545. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  546. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  547. package/dist/src/styles/cytoscape/mappings.js +92 -0
  548. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  549. package/dist/src/styles/cytoscape/resolve.d.ts +46 -3
  550. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  551. package/dist/src/styles/cytoscape/resolve.js +632 -22
  552. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  553. package/dist/src/styles/cytoscape/translate.d.ts.map +1 -1
  554. package/dist/src/styles/cytoscape/translate.js +10 -10
  555. package/dist/src/styles/cytoscape/translate.js.map +1 -1
  556. package/dist/src/styles/defaults.d.ts +50 -0
  557. package/dist/src/styles/defaults.d.ts.map +1 -1
  558. package/dist/src/styles/defaults.js +315 -37
  559. package/dist/src/styles/defaults.js.map +1 -1
  560. package/dist/src/styles/index.d.ts +4 -3
  561. package/dist/src/styles/index.d.ts.map +1 -1
  562. package/dist/src/styles/index.js +3 -2
  563. package/dist/src/styles/index.js.map +1 -1
  564. package/dist/src/styles/internal.d.ts +1 -0
  565. package/dist/src/styles/internal.d.ts.map +1 -1
  566. package/dist/src/styles/internal.js +1 -0
  567. package/dist/src/styles/internal.js.map +1 -1
  568. package/dist/src/styles/io/block.d.ts.map +1 -1
  569. package/dist/src/styles/io/block.js +9 -0
  570. package/dist/src/styles/io/block.js.map +1 -1
  571. package/dist/src/styles/io/generic.d.ts.map +1 -1
  572. package/dist/src/styles/io/generic.js +56 -16
  573. package/dist/src/styles/io/generic.js.map +1 -1
  574. package/dist/src/styles/io/round-trip.d.ts +56 -0
  575. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  576. package/dist/src/styles/io/round-trip.js +138 -0
  577. package/dist/src/styles/io/round-trip.js.map +1 -0
  578. package/dist/src/styles/io/writer.d.ts.map +1 -1
  579. package/dist/src/styles/io/writer.js +13 -4
  580. package/dist/src/styles/io/writer.js.map +1 -1
  581. package/dist/src/styles/notes.d.ts.map +1 -1
  582. package/dist/src/styles/notes.js +1 -0
  583. package/dist/src/styles/notes.js.map +1 -1
  584. package/dist/src/styles/plan/features.d.ts +1 -1
  585. package/dist/src/styles/plan/features.d.ts.map +1 -1
  586. package/dist/src/styles/plan/features.js +22 -2
  587. package/dist/src/styles/plan/features.js.map +1 -1
  588. package/dist/src/styles/plan/index.d.ts +1 -1
  589. package/dist/src/styles/plan/index.d.ts.map +1 -1
  590. package/dist/src/styles/plan/index.js +1 -1
  591. package/dist/src/styles/plan/index.js.map +1 -1
  592. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  593. package/dist/src/styles/plan/plan.js +61 -4
  594. package/dist/src/styles/plan/plan.js.map +1 -1
  595. package/dist/src/styles/plan/resolve.d.ts +13 -1
  596. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  597. package/dist/src/styles/plan/resolve.js +53 -6
  598. package/dist/src/styles/plan/resolve.js.map +1 -1
  599. package/dist/src/styles/slots.d.ts +14 -0
  600. package/dist/src/styles/slots.d.ts.map +1 -0
  601. package/dist/src/styles/slots.js +20 -0
  602. package/dist/src/styles/slots.js.map +1 -0
  603. package/dist/src/styles/types.d.ts +638 -5
  604. package/dist/src/styles/types.d.ts.map +1 -1
  605. package/dist/src/styles/vocabulary.d.ts +3 -2
  606. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  607. package/dist/src/styles/vocabulary.js +218 -1
  608. package/dist/src/styles/vocabulary.js.map +1 -1
  609. package/dist/src/types.d.ts +19 -5
  610. package/dist/src/types.d.ts.map +1 -1
  611. package/dist/src/types.js.map +1 -1
  612. package/dist/styles.js +29 -238
  613. package/dist/styles.js.map +1 -1
  614. package/dist/xgmml.js +3 -3
  615. package/docs/samples/people.json +6 -0
  616. package/package.json +53 -8
  617. package/src/common/report.ts +27 -7
  618. package/src/formats/cx/importer.ts +6 -1
  619. package/src/formats/cx/styles.ts +144 -9
  620. package/src/formats/cx2/importer.ts +1 -0
  621. package/src/formats/cx2/styles.ts +3 -1
  622. package/src/formats/cys/importer.ts +1 -0
  623. package/src/formats/cys/styles.ts +27 -5
  624. package/src/formats/dot/drawing.ts +799 -0
  625. package/src/formats/dot/importer.ts +120 -35
  626. package/src/formats/dot/label-places.ts +228 -0
  627. package/src/formats/dot/record.ts +336 -0
  628. package/src/formats/dot/styles.ts +1657 -154
  629. package/src/formats/gexf/dialog-metrics.ts +61 -0
  630. package/src/formats/gexf/importer.ts +50 -5
  631. package/src/formats/gexf/preview.ts +217 -0
  632. package/src/formats/gexf/schema.ts +2 -1
  633. package/src/formats/gexf/styles.ts +1144 -142
  634. package/src/formats/gml/importer.ts +291 -76
  635. package/src/formats/gml/index.ts +1 -1
  636. package/src/formats/gml/positions.ts +29 -7
  637. package/src/formats/gml/styles.ts +854 -111
  638. package/src/formats/graphml/styles-plain.ts +8 -23
  639. package/src/formats/graphml/styles-yed.ts +821 -159
  640. package/src/formats/graphml/styles-yfiles3.ts +485 -63
  641. package/src/formats/graphml/yfiles.ts +19 -6
  642. package/src/formats/json/dialect.ts +41 -5
  643. package/src/formats/json/importer.ts +59 -7
  644. package/src/formats/json/index.ts +1 -0
  645. package/src/formats/json/positions.ts +22 -5
  646. package/src/formats/json/styles.ts +2041 -185
  647. package/src/formats/pajek/draw.ts +458 -0
  648. package/src/formats/pajek/exporter.ts +81 -49
  649. package/src/formats/pajek/importer.ts +278 -103
  650. package/src/formats/pajek/index.ts +1 -0
  651. package/src/formats/pajek/styles.ts +1382 -133
  652. package/src/formats/pajek/syntax.ts +27 -2
  653. package/src/formats/xgmml/emit.ts +73 -5
  654. package/src/formats/xgmml/styles.ts +331 -71
  655. package/src/index.ts +94 -0
  656. package/src/positions/convert.ts +12 -1
  657. package/src/positions/extract.ts +55 -1
  658. package/src/positions/index.ts +1 -0
  659. package/src/positions/types.ts +60 -0
  660. package/src/registry.ts +326 -1
  661. package/src/sources/builtins.ts +63 -0
  662. package/src/sources/codes.ts +235 -0
  663. package/src/sources/context.ts +894 -0
  664. package/src/sources/credentials.ts +409 -0
  665. package/src/sources/cypher/descriptor.ts +131 -0
  666. package/src/sources/cypher/flatten.ts +323 -0
  667. package/src/sources/cypher/index.ts +628 -0
  668. package/src/sources/cypher/params.ts +41 -0
  669. package/src/sources/cypher/profiles.ts +78 -0
  670. package/src/sources/cypher/query-builder.ts +327 -0
  671. package/src/sources/cypher/transports/bolt.ts +228 -0
  672. package/src/sources/cypher/transports/neptune-analytics.ts +41 -0
  673. package/src/sources/cypher/transports/neptune-https.ts +122 -0
  674. package/src/sources/cypher/transports/query-api.ts +100 -0
  675. package/src/sources/cypher/transports/transport.ts +139 -0
  676. package/src/sources/cypher/types-map.ts +418 -0
  677. package/src/sources/define.ts +195 -0
  678. package/src/sources/fail.ts +70 -0
  679. package/src/sources/ids.ts +80 -0
  680. package/src/sources/ndex/client.ts +102 -0
  681. package/src/sources/ndex/descriptor.ts +64 -0
  682. package/src/sources/ndex/expand.ts +100 -0
  683. package/src/sources/ndex/index.ts +235 -0
  684. package/src/sources/ndex/params.ts +17 -0
  685. package/src/sources/ndex/share-url.ts +84 -0
  686. package/src/sources/params.ts +32 -0
  687. package/src/sources/registry.ts +325 -0
  688. package/src/sources/rest/descriptor.ts +79 -0
  689. package/src/sources/rest/index.ts +22 -0
  690. package/src/sources/rest/mapping.ts +401 -0
  691. package/src/sources/rest/openalex.ts +288 -0
  692. package/src/sources/rest/paging.ts +180 -0
  693. package/src/sources/rest/params.ts +243 -0
  694. package/src/sources/rest/records.ts +289 -0
  695. package/src/sources/rest/samples/deps-dev.ts +49 -0
  696. package/src/sources/rest/samples/string.ts +44 -0
  697. package/src/sources/rest/selectors.ts +91 -0
  698. package/src/sources/rest/source.ts +776 -0
  699. package/src/sources/rest/templates.ts +151 -0
  700. package/src/sources/run.ts +793 -0
  701. package/src/sources/sha256.ts +99 -0
  702. package/src/sources/sigv4.ts +209 -0
  703. package/src/sources/sparql/descriptor.ts +67 -0
  704. package/src/sources/sparql/index.ts +356 -0
  705. package/src/sources/sparql/ntriples.ts +219 -0
  706. package/src/sources/sparql/params.ts +28 -0
  707. package/src/sources/sparql/query.ts +162 -0
  708. package/src/sources/testing.ts +210 -0
  709. package/src/sources/types.ts +776 -0
  710. package/src/styles/annotations.ts +201 -27
  711. package/src/styles/canon/bends.ts +137 -0
  712. package/src/styles/canon/color-tables.ts +10 -4
  713. package/src/styles/canon/color.ts +105 -3
  714. package/src/styles/canon/enums.ts +99 -8
  715. package/src/styles/canon/graphviz.ts +71 -10
  716. package/src/styles/canon/number.ts +19 -0
  717. package/src/styles/canon/text.ts +187 -16
  718. package/src/styles/codes.ts +2 -0
  719. package/src/styles/cyjs/cascade.ts +1193 -38
  720. package/src/styles/cyjs/defaults-table.ts +5 -0
  721. package/src/styles/cyjs/emit.ts +247 -16
  722. package/src/styles/cyjs/face.ts +372 -0
  723. package/src/styles/cyjs/mappers.ts +498 -28
  724. package/src/styles/cyjs/routes.ts +432 -0
  725. package/src/styles/cytoscape/charts.ts +684 -0
  726. package/src/styles/cytoscape/emit.ts +220 -44
  727. package/src/styles/cytoscape/lexicon.ts +459 -80
  728. package/src/styles/cytoscape/mappings.ts +108 -0
  729. package/src/styles/cytoscape/resolve.ts +763 -23
  730. package/src/styles/cytoscape/translate.ts +11 -11
  731. package/src/styles/defaults.ts +436 -38
  732. package/src/styles/index.ts +5 -0
  733. package/src/styles/internal.ts +1 -0
  734. package/src/styles/io/block.ts +10 -0
  735. package/src/styles/io/generic.ts +79 -23
  736. package/src/styles/io/round-trip.ts +202 -0
  737. package/src/styles/io/writer.ts +14 -4
  738. package/src/styles/notes.ts +1 -0
  739. package/src/styles/plan/features.ts +23 -2
  740. package/src/styles/plan/index.ts +1 -1
  741. package/src/styles/plan/plan.ts +69 -5
  742. package/src/styles/plan/resolve.ts +61 -6
  743. package/src/styles/slots.ts +25 -0
  744. package/src/styles/types.ts +658 -4
  745. package/src/styles/vocabulary.ts +226 -3
  746. package/src/types.ts +19 -5
  747. package/dist/chunks/block-DiGq58c3.js.map +0 -1
  748. package/dist/chunks/choose--jM0yYCo.js +0 -57
  749. package/dist/chunks/choose--jM0yYCo.js.map +0 -1
  750. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  751. package/dist/chunks/emit-CwU8cUmG.js.map +0 -1
  752. package/dist/chunks/export-BvqAXCKh.js.map +0 -1
  753. package/dist/chunks/exporter-CrDWIyiq.js.map +0 -1
  754. package/dist/chunks/format-BpQBx8MZ.js.map +0 -1
  755. package/dist/chunks/generic-Dq1ntt9q.js.map +0 -1
  756. package/dist/chunks/importer-BSvfrX_h.js.map +0 -1
  757. package/dist/chunks/importer-CMmeMWlC.js.map +0 -1
  758. package/dist/chunks/importer-COTK9Tsl.js.map +0 -1
  759. package/dist/chunks/importer-DiZRmOQG.js.map +0 -1
  760. package/dist/chunks/importer-e6LGpqHB.js.map +0 -1
  761. package/dist/chunks/importer-iFYPEKaJ.js.map +0 -1
  762. package/dist/chunks/importer-yh_aBCU6.js.map +0 -1
  763. package/dist/chunks/lexicon-CT69Kd87.js.map +0 -1
  764. package/dist/chunks/styles-BQnsga7p.js.map +0 -1
  765. package/dist/chunks/styles-D3fRphrO.js +0 -690
  766. package/dist/chunks/styles-D3fRphrO.js.map +0 -1
  767. package/dist/chunks/styles-yed-BF5x3_Y5.js +0 -842
  768. package/dist/chunks/styles-yed-BF5x3_Y5.js.map +0 -1
  769. package/dist/chunks/writer-DMKvthQE.js +0 -448
  770. package/dist/chunks/writer-DMKvthQE.js.map +0 -1
@@ -11,16 +11,26 @@ import type { GraphSnapshot } from "@graphty/graph-format";
11
11
 
12
12
  import { toFilePositions, toNeutral } from "../../positions/convert.js";
13
13
  import type { PositionColumnExtra } from "../../positions/types.js";
14
- import { type BendPoint, bendsToPoints, canonBends } from "../../styles/canon/bends.js";
14
+ import {
15
+ type BendPoint,
16
+ bendsToPoints,
17
+ canonBends,
18
+ canonNodeOffsets,
19
+ flattenCubic,
20
+ flattenQuadSpline,
21
+ nodeOffsetsToPoints,
22
+ } from "../../styles/canon/bends.js";
15
23
  import { canonColor, colorOpacity } from "../../styles/canon/color.js";
16
24
  import { canonEnum } from "../../styles/canon/enums.js";
17
- import { canonNumber } from "../../styles/canon/number.js";
25
+ import { canonNumber, canonSigned } from "../../styles/canon/number.js";
18
26
  import { type CanonSite, MAX_STYLE_VALUE_LENGTH, noteAt } from "../../styles/canon/site.js";
19
27
  import { canonText } from "../../styles/canon/text.js";
20
28
  import { STYLE_ISSUE } from "../../styles/codes.js";
29
+ import { JAVA_MONO, JAVA_SANS, JAVA_SERIF, javaFamily } from "../../styles/cytoscape/lexicon.js";
21
30
  import { StyleApproximations } from "../../styles/io/approximations.js";
31
+ import { elementValues, takeFromBlock } from "../../styles/io/round-trip.js";
22
32
  import type { ExporterStyleInput } from "../../styles/io/writer.js";
23
- import type { StyleNotes } from "../../styles/notes.js";
33
+ import { StyleNotes } from "../../styles/notes.js";
24
34
  import { plainCell } from "../../styles/plan/resolve.js";
25
35
  import type { StyleTarget, StyleValue, StyleWorkBudget, StyleWriteCapabilities } from "../../styles/types.js";
26
36
  import type { LossNote } from "../../types.js";
@@ -235,36 +245,183 @@ function activeRealizer(proxy: unknown): Realizer | null {
235
245
  return all[Number.isInteger(active) && active >= 0 && active < all.length ? active : 0] ?? null;
236
246
  }
237
247
 
248
+ /** A shape a yEd configuration draws: a neutral shape, with its corners where it is a `polygon`. */
249
+ export interface YedOutline {
250
+ readonly shape: string;
251
+ /** The polygon's corners as neutral `shapePoints` (`x,y` fractions of the half sizes, y up). */
252
+ readonly points?: string;
253
+ }
254
+
238
255
  /**
239
- * yEd's flowchart palette (`com.yworks.flowchart.<name>`), by name, to the shape each draws. Matched whole, before
240
- * the words below: "data" is a parallelogram, but "storedData" and "directData" are not.
256
+ * Points along an elliptical arc, as `x,y` text: center (cx, cy), radii (rx, ry), from angle `from` to `to` (radians,
257
+ * counter-clockwise, y up), both ends included.
258
+ * @param cx - center x
259
+ * @param cy - center y
260
+ * @param rx - x radius
261
+ * @param ry - y radius
262
+ * @param from - first angle
263
+ * @param to - last angle
264
+ * @param steps - segments
265
+ * @returns the points
241
266
  */
242
- const FLOWCHART_SHAPES: ReadonlyMap<string, string> = new Map([
243
- ["process", "rectangle"],
244
- ["decision", "diamond"],
245
- ["terminator", "round-rectangle"],
246
- ["start1", "ellipse"],
247
- ["start2", "ellipse"],
248
- ["data", "parallelogram"],
249
- ["preparation", "hexagon"],
250
- ]);
267
+ function arcPoints(cx: number, cy: number, rx: number, ry: number, from: number, to: number, steps = 12): string[] {
268
+ return Array.from({ length: steps + 1 }, (_, i) => {
269
+ const t = from + ((to - from) * i) / steps;
270
+ return pointText(cx + rx * Math.cos(t), cy + ry * Math.sin(t));
271
+ });
272
+ }
273
+
274
+ /**
275
+ * Points along a wave y = y0 + amp * sin(pi * x), x from `x0` to `x1`.
276
+ * @param y0 - the wave's middle
277
+ * @param amp - its height
278
+ * @param x0 - first x
279
+ * @param x1 - last x
280
+ * @returns the points
281
+ */
282
+ function wavePoints(y0: number, amp: number, x0: number, x1: number): string[] {
283
+ const steps = 16;
284
+ return Array.from({ length: steps + 1 }, (_, i) => {
285
+ const x = x0 + ((x1 - x0) * i) / steps;
286
+ return pointText(x, y0 + amp * Math.sin(Math.PI * x));
287
+ });
288
+ }
289
+
290
+ /**
291
+ * One corner as `x,y`, rounded to three decimals.
292
+ * @param x - x
293
+ * @param y - y
294
+ * @returns the text
295
+ */
296
+ function pointText(x: number, y: number): string {
297
+ const r = (v: number): string => String(Math.round(v * 1000) / 1000 + 0);
298
+ return `${r(x)},${r(y)}`;
299
+ }
300
+
301
+ const HALF_PI = Math.PI / 2;
302
+
303
+ /** A cloud: a circle of bumps, stretched to the box. */
304
+ const CLOUD = Array.from({ length: 72 }, (_, i) => {
305
+ const t = (2 * Math.PI * i) / 72;
306
+ const r = 0.86 + 0.14 * Math.abs(Math.cos(4 * t));
307
+ return pointText(r * Math.cos(t), r * Math.sin(t));
308
+ }).join(" ");
251
309
 
252
- const FLOWCHART_PREFIX = "com.yworks.flowchart.";
310
+ /** A stadium: a box whose ends are half circles (a pill). */
311
+ const STADIUM = [
312
+ ...arcPoints(0.5, 0, 0.5, 1, -HALF_PI, HALF_PI),
313
+ ...arcPoints(-0.5, 0, 0.5, 1, HALF_PI, 3 * HALF_PI),
314
+ ].join(" ");
253
315
 
254
316
  /**
255
- * The shape a yEd flowchart configuration draws: a GraphML GenericNode's `configuration`, or a yEd GML node's
317
+ * The shape each configuration of yEd's GenericNode palettes draws (flowchart, entity relationship, BPMN, SBGN), by
318
+ * its name after `com.yworks.` without a `.withShadow` suffix, lowercase. Matched whole, before the words below:
319
+ * "data" is a parallelogram, but "storedData" and "directData" are not. A shape no neutral one names is the polygon
320
+ * yEd draws it as (curves as short segments); the lines some draw inside (predefined process, internal storage) are
321
+ * not drawn. Left out until a drawing by yEd itself shows them (ISSUES.md): the BPMN artifact, whose `type` property
322
+ * picks among a data object, a data store, a message and others, and the SBGN nucleic acid feature and perturbing
323
+ * agent, which draw.io, the stand-in, draws as plain boxes.
324
+ */
325
+ const YED_CONFIGURATIONS: ReadonlyMap<string, YedOutline> = new Map<string, YedOutline>([
326
+ ["flowchart.process", { shape: "rectangle" }],
327
+ ["flowchart.predefinedprocess", { shape: "rectangle" }],
328
+ ["flowchart.internalstorage", { shape: "rectangle" }],
329
+ ["flowchart.decision", { shape: "diamond" }],
330
+ ["flowchart.terminator", { shape: "round-rectangle" }],
331
+ ["flowchart.start1", { shape: "ellipse" }],
332
+ ["flowchart.start2", { shape: "ellipse" }],
333
+ ["flowchart.onpagereference", { shape: "ellipse" }],
334
+ ["flowchart.sequentialdata", { shape: "ellipse" }],
335
+ ["flowchart.data", { shape: "parallelogram" }],
336
+ ["flowchart.preparation", { shape: "hexagon" }],
337
+ ["flowchart.database", { shape: "other:database" }],
338
+ ["flowchart.looplimit", { shape: "polygon", points: "-1,-1 1,-1 1,0.5 0.8,1 -0.8,1 -1,0.5" }],
339
+ ["flowchart.looplimitend", { shape: "polygon", points: "-1,1 -1,-0.5 -0.8,-1 0.8,-1 1,-0.5 1,1" }],
340
+ ["flowchart.manualinput", { shape: "polygon", points: "-1,-1 1,-1 1,1 -1,0.4" }],
341
+ ["flowchart.card", { shape: "polygon", points: "-1,-1 1,-1 1,1 -0.6,1 -1,0.6" }],
342
+ ["flowchart.manualoperation", { shape: "polygon", points: "-1,1 -0.7,-1 0.7,-1 1,1" }],
343
+ ["flowchart.offpagereference", { shape: "polygon", points: "-1,1 -1,0 0,-1 1,0 1,1" }],
344
+ ["flowchart.usermessage", { shape: "polygon", points: "-1,1 -1,-1 0.6,-1 1,0 0.6,1" }],
345
+ ["flowchart.networkmessage", { shape: "polygon", points: "-1,1 -0.6,0 -1,-1 1,-1 1,1" }],
346
+ ["flowchart.document", { shape: "polygon", points: ["-1,1", ...wavePoints(-0.75, 0.2, -1, 1), "1,1"].join(" ") }],
347
+ [
348
+ "flowchart.papertype",
349
+ {
350
+ shape: "polygon",
351
+ points: [...wavePoints(-0.8, 0.2, -1, 1), ...wavePoints(0.8, 0.2, 1, -1)].join(" "),
352
+ },
353
+ ],
354
+ [
355
+ "flowchart.delay",
356
+ { shape: "polygon", points: ["-1,-1", ...arcPoints(0, 0, 1, 1, -HALF_PI, HALF_PI), "-1,1"].join(" ") },
357
+ ],
358
+ [
359
+ "flowchart.display",
360
+ {
361
+ shape: "polygon",
362
+ points: ["-1,0", "-0.6,-1", ...arcPoints(0.6, 0, 0.4, 1, -HALF_PI, HALF_PI), "-0.6,1"].join(" "),
363
+ },
364
+ ],
365
+ [
366
+ "flowchart.storeddata",
367
+ {
368
+ shape: "polygon",
369
+ points: [
370
+ ...arcPoints(1, 0, -0.2, 1, -HALF_PI, HALF_PI),
371
+ ...arcPoints(-0.8, 0, 0.2, 1, HALF_PI, 3 * HALF_PI),
372
+ ].join(" "),
373
+ },
374
+ ],
375
+ [
376
+ "flowchart.directdata",
377
+ {
378
+ shape: "polygon",
379
+ points: [
380
+ ...arcPoints(0.8, 0, 0.2, 1, -HALF_PI, HALF_PI),
381
+ ...arcPoints(-0.8, 0, 0.2, 1, HALF_PI, 3 * HALF_PI),
382
+ ].join(" "),
383
+ },
384
+ ],
385
+ ["flowchart.cloud", { shape: "polygon", points: CLOUD }],
386
+ ["entityrelationship.relationship", { shape: "diamond" }],
387
+ ["entityrelationship.attribute", { shape: "ellipse" }],
388
+ ["bpmn.conversation", { shape: "hexagon" }],
389
+ ["sbgn.unspecifiedentity", { shape: "ellipse" }],
390
+ ["sbgn.simplechemical", { shape: "ellipse" }],
391
+ ["sbgn.emptyset", { shape: "ellipse" }],
392
+ ["sbgn.operator", { shape: "ellipse" }],
393
+ ["sbgn.macromolecule", { shape: "round-rectangle" }],
394
+ ["sbgn.phenotype", { shape: "hexagon" }],
395
+ ["sbgn.process", { shape: "rectangle" }],
396
+ ["sbgn.submap", { shape: "rectangle" }],
397
+ ["sbgn.unitofinformation", { shape: "rectangle" }],
398
+ ["sbgn.statevariable", { shape: "polygon", points: STADIUM }],
399
+ ["sbgn.tag", { shape: "polygon", points: "-1,1 -1,-1 0.6,-1 1,0 0.6,1" }],
400
+ ]);
401
+
402
+ /**
403
+ * The shape a yEd GenericNode configuration draws: a GraphML GenericNode's `configuration`, or a yEd GML node's
256
404
  * `customconfiguration`.
257
405
  * @param configuration - the configuration
258
- * @returns the neutral shape, or null for a configuration that is not one of the flowchart shapes known here
406
+ * @returns the shape, with its corners where it is a polygon, or null for a configuration not known here
259
407
  */
260
- export function flowchartShape(configuration: string): string | null {
261
- return configuration.startsWith(FLOWCHART_PREFIX)
262
- ? (FLOWCHART_SHAPES.get(configuration.slice(FLOWCHART_PREFIX.length)) ?? null)
263
- : null;
408
+ export function configurationOutline(configuration: string): YedOutline | null {
409
+ const key = configuration
410
+ .slice(0, MAX_STYLE_VALUE_LENGTH)
411
+ .toLowerCase()
412
+ .replace(/^com\.yworks\./, "")
413
+ .replace(/\.withshadow$/, "");
414
+ return YED_CONFIGURATIONS.get(key) ?? null;
264
415
  }
265
416
 
266
417
  /** GenericNode configurations, by a word they contain, to the shape they draw; the first match wins. */
267
418
  const GENERIC_SHAPES: readonly (readonly [string, string])[] = [
419
+ // yEd's BPMN and entity-relationship palettes: a task is a rounded box, an event a circle, a
420
+ // gateway a diamond, an attribute an ellipse
421
+ ["bpmn.activity", "round-rectangle"],
422
+ ["bpmn.event", "ellipse"],
423
+ ["bpmn.gateway", "diamond"],
424
+ ["entityrelationship.attribute", "ellipse"],
268
425
  ["ellipse", "ellipse"],
269
426
  ["circle", "ellipse"],
270
427
  ["oval", "ellipse"],
@@ -278,7 +435,11 @@ const GENERIC_SHAPES: readonly (readonly [string, string])[] = [
278
435
  ["box", "rectangle"],
279
436
  ];
280
437
 
281
- /** yEd's label positions (`modelPosition` of the internal, sides and eight-position models). */
438
+ /**
439
+ * yEd's label positions (`modelPosition` of the internal, sides, sandwich, corners and eight-position models). The
440
+ * internal model's `t` (inside the top of the box: a group's title) is `inside-top`; its other inside positions have
441
+ * no neutral value and read as the nearest side or corner.
442
+ */
282
443
  const YED_POSITIONS: ReadonlyMap<string, string> = new Map([
283
444
  ["c", "center"],
284
445
  ["t", "top"],
@@ -334,8 +495,9 @@ function readColor(raw: unknown, property: string, opacity: string | null, put:
334
495
  * @param node - whether they are node labels (which have a position)
335
496
  * @param put - receives the values
336
497
  * @param at - the sites
498
+ * @param geometry - a node label's node `y:Geometry`, which places the label inside or outside the node
337
499
  */
338
- function readLabels(labels: readonly unknown[], node: boolean, put: PutValue, at: SiteOf): void {
500
+ function readLabels(labels: readonly unknown[], node: boolean, put: PutValue, at: SiteOf, geometry?: unknown): void {
339
501
  let label: unknown = undefined;
340
502
  let text = "";
341
503
  let extra = 0;
@@ -358,20 +520,33 @@ function readLabels(labels: readonly unknown[], node: boolean, put: PutValue, at
358
520
  noteAt(at("label"), STYLE_ISSUE.EXTRA_LABELS, `${String(extra + 1)} labels`);
359
521
  }
360
522
  put("label", canonText(text, at("label")));
361
- readLabelLook(label, node, put, at);
523
+ readLabelLook(label, node, put, at, geometry);
362
524
  }
363
525
 
364
526
  /**
365
- * Reads a label's look: its color, font and, for a node label, its position.
527
+ * Reads a label's look: its color, background box and its border, font and, for a node label, its position.
366
528
  * @param label - the label element
367
529
  * @param node - whether it is a node label
368
530
  * @param put - receives the values
369
531
  * @param at - the sites
532
+ * @param geometry - a node label's node `y:Geometry`
370
533
  */
371
- function readLabelLook(label: unknown, node: boolean, put: PutValue, at: SiteOf): void {
534
+ function readLabelLook(label: unknown, node: boolean, put: PutValue, at: SiteOf, geometry?: unknown): void {
372
535
  readColor(treeAttr(label, "textColor"), "labelColor", null, put, at);
536
+ // yEd draws a box behind the words in `backgroundColor` unless `hasBackgroundColor` is false
537
+ if (treeAttr(label, "hasBackgroundColor") !== "false") {
538
+ readColor(treeAttr(label, "backgroundColor"), "labelBackground", null, put, at);
539
+ }
540
+ // and a one-pixel line round that box in `lineColor` unless `hasLineColor` is false
541
+ if (treeAttr(label, "hasLineColor") !== "false" && treeAttr(label, "lineColor") !== undefined) {
542
+ readColor(treeAttr(label, "lineColor"), "labelBorderColor", null, put, at);
543
+ put("labelBorderWidth", 1);
544
+ }
373
545
  put("labelSize", canonNumber(treeAttr(label, "fontSize"), at("labelSize")));
374
- put("labelFont", canonText(treeAttr(label, "fontFamily"), at("labelFont")));
546
+ // yEd is a Java program: its logical fonts (Dialog, SansSerif, Monospaced, ...) are drawn in the faces Java gives
547
+ // them, and a font it does not have in Dialog's
548
+ const font = canonText(treeAttr(label, "fontFamily"), at("labelFont"));
549
+ put("labelFont", font === null ? null : javaFamily(font));
375
550
  const style = treeAttr(label, "fontStyle");
376
551
  if (style !== undefined) {
377
552
  const known = FONT_STYLES.get(style.trim().toLowerCase());
@@ -382,16 +557,254 @@ function readLabelLook(label: unknown, node: boolean, put: PutValue, at: SiteOf)
382
557
  put("labelItalic", known[1]);
383
558
  }
384
559
  }
385
- const position = node ? treeAttr(label, "modelPosition") : undefined;
386
- if (position !== undefined) {
387
- const known = YED_POSITIONS.get(position.trim().toLowerCase());
388
- if (known === undefined) {
389
- noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, position.slice(0, MAX_STYLE_VALUE_LENGTH));
560
+ readRotation(label, put, at);
561
+ if (node) {
562
+ const position = nodeLabelPosition(label, geometry, at);
563
+ put("labelPosition", position);
564
+ readInsideInset(label, geometry, position, put);
565
+ readOutsideOffset(label, geometry, position, put);
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Reads a label's `rotationAngle`: yEd is a Java2D program, whose angles turn clockwise on screen (y down), as the
571
+ * neutral `labelRotation` does.
572
+ * @param label - the label element
573
+ * @param put - receives the values
574
+ * @param at - the sites
575
+ */
576
+ function readRotation(label: unknown, put: PutValue, at: SiteOf): void {
577
+ const angle = canonSigned(treeAttr(label, "rotationAngle"), at("labelRotation"));
578
+ if (angle === null) {
579
+ return;
580
+ }
581
+ const turn = ((angle % 360) + 360) % 360;
582
+ put("labelRotation", turn === 0 ? null : turn);
583
+ }
584
+
585
+ /**
586
+ * How far from where its position puts it a label outside its node, or placed freely, is drawn: yEd writes every
587
+ * label's box as it draws it, so an outside label keeps its model's distance from the node (4 by default) and a
588
+ * free label its offset. Across the side it is beside, the label is moved by the gap between the node and its box;
589
+ * along that side (and on both axes for a free label over the node), by how far its box's middle is from the node's.
590
+ * A turned label's box is not its words' box, so it is left where its position puts it.
591
+ * @param label - the label element
592
+ * @param geometry - the node's `y:Geometry`
593
+ * @param position - where the label is placed
594
+ * @param put - receives the values
595
+ */
596
+ function readOutsideOffset(label: unknown, geometry: unknown, position: string | null, put: PutValue): void {
597
+ const model = treeAttr(label, "modelName");
598
+ const free = position === "center" && model !== undefined && model !== "internal";
599
+ if (position === null || position.startsWith("inside-") || (position === "center" && !free)) {
600
+ return;
601
+ }
602
+ if (Number(treeAttr(label, "rotationAngle") ?? 0) % 360 !== 0) {
603
+ return;
604
+ }
605
+ const num = (o: unknown, k: string): number => Number(treeAttr(o, k) ?? Number.NaN);
606
+ const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
607
+ const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
608
+ if (![x, y, w, h, nw, nh].every(Number.isFinite)) {
609
+ return;
610
+ }
611
+ const signed = (value: number): number | null => {
612
+ const r = Math.round(value * 1000) / 1000;
613
+ return r === 0 ? null : r;
614
+ };
615
+ // across a side: the gap between the node and the box; along it: the box's middle against the node's
616
+ const offset = (lo: number, size: number, extent: number, before: boolean, after: boolean): number | null => {
617
+ if (before) {
618
+ return signed(lo + size);
390
619
  }
391
- put("labelPosition", known ?? null);
620
+ return after ? signed(lo - extent) : signed(lo + size / 2 - extent / 2);
621
+ };
622
+ put("labelOffsetX", offset(x, w, nw, position.includes("left"), position.includes("right")));
623
+ put("labelOffsetY", offset(y, h, nh, position.includes("top"), position.includes("bottom")));
624
+ }
625
+
626
+ /**
627
+ * How far in from the sides it is drawn against yEd puts a label inside its node (its internal model's insets, 4 by
628
+ * default), from the label's stored box, for a label sized to its words: the label is moved that far right of a left side, left of a right side, down
629
+ * from the top and up from the bottom.
630
+ * @param label - the label element
631
+ * @param geometry - the node's `y:Geometry`
632
+ * @param position - where the label is placed
633
+ * @param put - receives the values
634
+ */
635
+ function readInsideInset(label: unknown, geometry: unknown, position: string | null, put: PutValue): void {
636
+ // a label sized to its node (a group's header band) has a box that is not its words'
637
+ const sized = treeAttr(label, "autoSizePolicy")?.startsWith("node_") === true;
638
+ if (position?.startsWith("inside-") !== true || sized) {
639
+ return;
640
+ }
641
+ const num = (o: unknown, k: string): number => Number(treeAttr(o, k) ?? Number.NaN);
642
+ const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
643
+ const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
644
+ const inset = (value: number): number | null =>
645
+ Number.isFinite(value) && value > 0 ? Math.round(value * 1000) / 1000 : null;
646
+ if (position.includes("left")) {
647
+ put("labelOffsetX", inset(x));
648
+ } else if (position.includes("right")) {
649
+ const gap = inset(nw - x - w);
650
+ put("labelOffsetX", gap === null ? null : -gap);
651
+ }
652
+ if (position.includes("top")) {
653
+ put("labelOffsetY", inset(y));
654
+ } else if (position.includes("bottom")) {
655
+ const gap = inset(nh - y - h);
656
+ put("labelOffsetY", gap === null ? null : -gap);
657
+ }
658
+ }
659
+
660
+ /**
661
+ * Where yEd draws a node label: from the label's box, which every model yEd writes stores relative to the node's
662
+ * top-left corner (a label entirely beside the node is outside it on that side), else from its model. A label inside
663
+ * the node is placed by its model: yEd's `internal` model puts it against a side or in a corner (`t`, `bl`, ...), or
664
+ * in the middle (`c`); any other model's label inside the node is in its middle.
665
+ * @param label - the label element
666
+ * @param geometry - the node's `y:Geometry`
667
+ * @param at - the sites
668
+ * @returns the position, or null
669
+ */
670
+ function nodeLabelPosition(label: unknown, geometry: unknown, at: SiteOf): string | null {
671
+ const outside = boxPosition(label, geometry);
672
+ if (outside !== null && outside !== "center") {
673
+ return outside;
674
+ }
675
+ const position = treeAttr(label, "modelPosition");
676
+ const model = treeAttr(label, "modelName");
677
+ if (model === "internal") {
678
+ return insidePosition(label, position);
679
+ }
680
+ if (model === "custom") {
681
+ return customPosition(label, outside, at);
682
+ }
683
+ if (outside !== null || position === undefined) {
684
+ return outside;
685
+ }
686
+ const known = YED_POSITIONS.get(position.trim().toLowerCase());
687
+ if (known === undefined) {
688
+ noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, position.slice(0, MAX_STYLE_VALUE_LENGTH));
392
689
  }
690
+ return known ?? null;
393
691
  }
394
692
 
693
+ /**
694
+ * Where a SmartNodeLabelModel (`custom`) label is drawn: where its stored box puts it, as for any other model, and
695
+ * where its ratios put it when the file stores no box (a label hung from the node's top edge into it is a header
696
+ * along its top). A box beside the node is handled before this.
697
+ * @param label - the label element
698
+ * @param outside - the box's position against the node, `center` or null
699
+ * @param at - the sites
700
+ * @returns the position, or null
701
+ */
702
+ function customPosition(label: unknown, outside: string | null, at: SiteOf): string | null {
703
+ const smart = treeChild(treeChild(label, "ModelParameter"), "SmartNodeLabelModelParameter");
704
+ if (smart === undefined) {
705
+ noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, "custom");
706
+ return outside;
707
+ }
708
+ // the stored box is where yEd drew the label; the ratios place it only when the file stores no box
709
+ return outside ?? smartPosition(smart);
710
+ }
711
+
712
+ /**
713
+ * The nearest neutral position of a SmartNodeLabelModel placement. yEd puts the point `labelRatio` of the label
714
+ * (-0.5..0.5 of its size from its center) on the point `nodeRatio` of the node; the offsets are ignored. On each axis
715
+ * a node ratio below or above zero is that side, zero is the middle. A label on the node's top edge that hangs down
716
+ * into it (labelRatioY at or below zero) is `inside-top`; every other edge or corner placement is the outside side
717
+ * or corner, the nearest neutral value (an inside bottom or side has none).
718
+ * @param smart - the `y:SmartNodeLabelModelParameter` element
719
+ * @returns the position
720
+ */
721
+ function smartPosition(smart: unknown): string {
722
+ const ratio = (name: string): number => {
723
+ const n = Number(treeAttr(smart, name));
724
+ return Number.isFinite(n) ? n : 0;
725
+ };
726
+ const h = sideOf(ratio("nodeRatioX"), "left", "right");
727
+ const v = sideOf(ratio("nodeRatioY"), "top", "bottom");
728
+ if (v === "top" && h === "" && ratio("labelRatioY") <= 0) {
729
+ return "inside-top";
730
+ }
731
+ if (v === "" || h === "") {
732
+ return v + h || "center";
733
+ }
734
+ return `${v}-${h}`;
735
+ }
736
+
737
+ /**
738
+ * One axis of a SmartNodeLabelModel node ratio.
739
+ * @param ratio - the ratio, -0.5..0.5
740
+ * @param low - the side below zero
741
+ * @param high - the side above zero
742
+ * @returns the side, or "" for the middle
743
+ */
744
+ function sideOf(ratio: number, low: string, high: string): string {
745
+ if (ratio < 0) {
746
+ return low;
747
+ }
748
+ return ratio > 0 ? high : "";
749
+ }
750
+
751
+ /**
752
+ * Where a label's box lies against its node: beside a side or a corner, or `center` when it overlaps the node.
753
+ * @param label - the label element
754
+ * @param geometry - the node's `y:Geometry`
755
+ * @returns the position, or null when the label or the node has no box
756
+ */
757
+ function boxPosition(label: unknown, geometry: unknown): string | null {
758
+ const num = (o: unknown, k: string): number => Number(treeAttr(o, k) ?? Number.NaN);
759
+ const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
760
+ const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
761
+ if (![x, y, w, h, nw, nh].every(Number.isFinite)) {
762
+ return null;
763
+ }
764
+ const side = (lo: number, size: number, extent: number): -1 | 0 | 1 => {
765
+ if (lo + size <= 0) {
766
+ return -1;
767
+ }
768
+ return lo >= extent ? 1 : 0;
769
+ };
770
+ return BOX_POSITIONS[side(y, h, nh) + 1][side(x, w, nw) + 1];
771
+ }
772
+
773
+ /**
774
+ * Where yEd's internal model draws a label: in the middle, or inside the node against the side or in the corner its
775
+ * `modelPosition` names. A label as wide as its node (a group's header) is drawn against the side its `alignment`
776
+ * names, so a right-aligned header along the top is in the top-right corner.
777
+ * @param label - the label element
778
+ * @param position - its `modelPosition`
779
+ * @returns the position
780
+ */
781
+ function insidePosition(label: unknown, position: string | undefined): string {
782
+ const inside = INTERNAL_POSITIONS.get((position ?? "c").trim().toLowerCase()) ?? "center";
783
+ const align = treeAttr(label, "alignment");
784
+ const across = treeAttr(label, "autoSizePolicy") === "node_width" && (align === "left" || align === "right");
785
+ return across && (inside === "inside-top" || inside === "inside-bottom") ? `${inside}-${align}` : inside;
786
+ }
787
+
788
+ /** yEd's internal label model positions, as the neutral position inside the node. */
789
+ const INTERNAL_POSITIONS: ReadonlyMap<string, string> = new Map([
790
+ ["c", "center"],
791
+ ["t", "inside-top"],
792
+ ["b", "inside-bottom"],
793
+ ["l", "inside-left"],
794
+ ["r", "inside-right"],
795
+ ["tl", "inside-top-left"],
796
+ ["tr", "inside-top-right"],
797
+ ["bl", "inside-bottom-left"],
798
+ ["br", "inside-bottom-right"],
799
+ ]);
800
+
801
+ /** A label's position by the side of the node it lies on: rows above, level, below; columns left, level, right. */
802
+ const BOX_POSITIONS: readonly (readonly string[])[] = [
803
+ ["top-left", "top", "top-right"],
804
+ ["left", "center", "right"],
805
+ ["bottom-left", "bottom", "bottom-right"],
806
+ ];
807
+
395
808
  /**
396
809
  * The shape of a node realizer: its `y:Shape` where it has one, a GenericNode's configuration, or the realizer
397
810
  * type itself for one that draws an image (SVG, image, table, UML).
@@ -407,11 +820,15 @@ function realizerShape(real: Realizer, at: SiteOf): string | null {
407
820
  if (real.type === "ShapeNode" || real.type === "GroupNode" || real.type === "GenericGroupNode") {
408
821
  return null;
409
822
  }
823
+ if (real.type === "TableNode") {
824
+ // a yEd table or pool is a rectangle of bands
825
+ return canonEnum("shape", "rectangle", "yed", at("shape"));
826
+ }
410
827
  if (real.type === "GenericNode") {
411
828
  const conf = treeAttr(real.r, "configuration") ?? "";
412
- const flowchart = flowchartShape(conf);
413
- if (flowchart !== null) {
414
- return flowchart;
829
+ const known = configurationOutline(conf);
830
+ if (known !== null) {
831
+ return known.shape;
415
832
  }
416
833
  const lower = conf.slice(0, MAX_STYLE_VALUE_LENGTH).toLowerCase();
417
834
  for (const [word, value] of GENERIC_SHAPES) {
@@ -429,27 +846,176 @@ function realizerShape(real: Realizer, at: SiteOf): string | null {
429
846
  return `other:${real.type}`;
430
847
  }
431
848
 
849
+ /** yEd's gradient: from the fill color at a node's top-left corner to `color2` at its bottom-right one. */
850
+ const YED_GRADIENT_ANGLE = 45;
851
+
432
852
  /**
433
- * Reads one node realizer.
853
+ * Reads a node realizer's fill: its color, and a gradient into `color2`. yEd paints no fill where the fill has no
854
+ * color or is transparent.
434
855
  * @param real - the realizer
435
856
  * @param put - receives the values
436
857
  * @param at - the sites
437
858
  */
438
- function readNode(real: Realizer, put: PutValue, at: SiteOf): void {
439
- const { r } = real;
440
- const fill = treeChild(r, "Fill");
441
- if (fill !== undefined) {
442
- if (treeAttr(fill, "hasColor") === "false" || treeAttr(fill, "transparent") === "true") {
443
- noteAt(at("fill"), STYLE_ISSUE.NO_FILL, "transparent");
444
- put("fillOpacity", 0);
445
- } else {
446
- readColor(treeAttr(fill, "color"), "fill", "fillOpacity", put, at);
447
- const second = treeAttr(fill, "color2");
448
- if (second !== undefined) {
449
- noteAt(at("fill"), STYLE_ISSUE.GRADIENT, second);
859
+ function readFill(real: Realizer, put: PutValue, at: SiteOf): void {
860
+ const fill = treeChild(real.r, "Fill");
861
+ if (fill === undefined) {
862
+ return;
863
+ }
864
+ if (treeAttr(fill, "hasColor") === "false" || treeAttr(fill, "transparent") === "true") {
865
+ noteAt(at("fill"), STYLE_ISSUE.NO_FILL, "transparent");
866
+ put("fillOpacity", 0);
867
+ return;
868
+ }
869
+ readColor(treeAttr(fill, "color"), "fill", "fillOpacity", put, at);
870
+ const second = canonColor(treeAttr(fill, "color2"), "yed", at("fillGradient"));
871
+ if (second !== null) {
872
+ put("fillGradient", second.color);
873
+ put("fillGradientAngle", YED_GRADIENT_ANGLE);
874
+ }
875
+ }
876
+
877
+ /**
878
+ * A `y:TableNode`'s `yed.table.*` style property, as a color.
879
+ * @param real - the table realizer
880
+ * @param name - the property's name
881
+ * @param at - the sites
882
+ * @returns the `#rrggbb` color, or null when the table does not set it
883
+ */
884
+ function tableColor(real: Realizer, name: string, at: SiteOf): string | null {
885
+ const props = treeChildren(treeChild(real.r, "StyleProperties"), "Property");
886
+ const prop = props.find((p) => treeAttr(p, "name") === name);
887
+ return prop === undefined ? null : (canonColor(treeAttr(prop, "value"), "yed", at("stripeColors"))?.color ?? null);
888
+ }
889
+
890
+ /**
891
+ * Reads a `y:TableNode` (a yEd table or BPMN pool) as bands over the node: its header (the table's top inset, or
892
+ * its left one for columns side by side) in `yed.table.header.color.main`, then its rows top to bottom (or its
893
+ * columns left to right) in `yed.table.lane.color.main` and `.alternating` by turns, then the opposite inset. A
894
+ * color the table does not set is the node's fill. The lines between the lanes and the row and column headers
895
+ * (`yed.table.header.color.alternating`) are not drawn.
896
+ * @param real - the realizer
897
+ * @param put - receives the values
898
+ * @param at - the sites
899
+ */
900
+ function readTable(real: Realizer, put: PutValue, at: SiteOf): void {
901
+ const table = treeChild(real.r, "Table");
902
+ const rows = treeChildren(treeChild(table, "Rows"), "Row");
903
+ const columns = treeChildren(treeChild(table, "Columns"), "Column");
904
+ const across = columns.length > 1 && rows.length <= 1;
905
+ const lanes = (across ? columns : rows).map((l) => Number(treeAttr(l, across ? "width" : "height")));
906
+ const insets = treeChild(table, "Insets");
907
+ const inset = (side: string): number => Math.max(0, Number(treeAttr(insets, side) ?? 0) || 0);
908
+ const [head, tail] = across ? [inset("left"), inset("right")] : [inset("top"), inset("bottom")];
909
+ const sizes = [head, ...lanes, tail];
910
+ const total = sizes.reduce((a, b) => a + b, 0);
911
+ if (lanes.length === 0 || !sizes.every(Number.isFinite) || total <= 0) {
912
+ return;
913
+ }
914
+ const fill =
915
+ canonColor(treeAttr(treeChild(real.r, "Fill"), "color"), "yed", at("stripeColors"))?.color ?? "#ffffff";
916
+ const main = tableColor(real, "yed.table.lane.color.main", at) ?? fill;
917
+ const alternating = tableColor(real, "yed.table.lane.color.alternating", at) ?? main;
918
+ const header = tableColor(real, "yed.table.header.color.main", at) ?? fill;
919
+ const bands = (
920
+ [[head, header], ...lanes.map((size, i) => [size, i % 2 === 0 ? main : alternating]), [tail, fill]] as [
921
+ number,
922
+ string,
923
+ ][]
924
+ ).filter(([size]) => size > 0);
925
+ put("stripeColors", bands.map(([, color]) => color).join(" "));
926
+ put("stripeSizes", bands.map(([size]) => String(Number((size / total).toFixed(6)))).join(" "));
927
+ if (across) {
928
+ put("stripeDirection", "right");
929
+ }
930
+ }
931
+
932
+ /**
933
+ * yEd's shared pictures (`<y:Resources>` on the graph): each resource's id to the picture as a URL, an SVG's text as
934
+ * a `data:image/svg+xml` URL and a `java.awt.image.BufferedImage` (base64 PNG) as a `data:image/png` one.
935
+ * @param snapshot - the graph
936
+ * @returns the pictures by id
937
+ */
938
+ function yedResources(snapshot: GraphSnapshot): ReadonlyMap<string, string> {
939
+ const out = new Map<string, string>();
940
+ for (const col of snapshot.graph) {
941
+ if (col.dtype !== "json" || col.meta.origin?.namespace !== "yfiles") {
942
+ continue;
943
+ }
944
+ addYedResources(plainCell(snapshot.graph.value(col.meta.name, 0)), out);
945
+ }
946
+ return out;
947
+ }
948
+
949
+ /**
950
+ * Adds the pictures of one yFiles graph value's `<y:Resources>`; an id already there keeps its picture.
951
+ * @param root - the graph's yFiles value
952
+ * @param out - the pictures by id, added to
953
+ */
954
+ function addYedResources(root: unknown, out: Map<string, string>): void {
955
+ for (const resources of treeChildren(root, "Resources")) {
956
+ for (const r of treeChildren(resources, "Resource")) {
957
+ const id = treeAttr(r, "id");
958
+ const url = id === undefined || out.has(id) ? null : yedResourceUrl(r);
959
+ if (id !== undefined && url !== null) {
960
+ out.set(id, url);
450
961
  }
451
962
  }
452
963
  }
964
+ }
965
+
966
+ /**
967
+ * One `<y:Resource>` as a picture URL: a `java.awt.image.BufferedImage` (base64 PNG) as a `data:image/png` URL and
968
+ * an SVG's text as a `data:image/svg+xml` one.
969
+ * @param r - the resource element
970
+ * @returns the URL, or null for an empty resource or one that is no picture
971
+ */
972
+ function yedResourceUrl(r: unknown): string | null {
973
+ const text = treeText(r)?.trim() ?? "";
974
+ if (text === "") {
975
+ return null;
976
+ }
977
+ const type = treeAttr(r, "type") ?? "";
978
+ if (type.endsWith("BufferedImage")) {
979
+ return `data:image/png;base64,${text.replaceAll(/\s+/g, "")}`;
980
+ }
981
+ if (text.includes("<svg")) {
982
+ return `data:image/svg+xml;utf8,${encodeURIComponent(text)}`;
983
+ }
984
+ return null;
985
+ }
986
+
987
+ /**
988
+ * The picture an image or SVG node realizer draws (`y:Image refid`, `y:SVGModel/y:SVGContent refid`), stretched over
989
+ * the node's box, as yEd draws `y:ImageNode` and `y:SVGNode`. The realizer's own fill and border are kept beneath it:
990
+ * whether yEd paints them under the picture waits for a drawing by yEd itself (ISSUES.md).
991
+ * @param real - the realizer
992
+ * @param resources - the graph's shared pictures
993
+ * @param put - receives the values
994
+ */
995
+ function readPicture(real: Realizer, resources: ReadonlyMap<string, string>, put: PutValue): void {
996
+ const ref =
997
+ real.type === "ImageNode"
998
+ ? treeAttr(treeChild(real.r, "Image"), "refid")
999
+ : treeAttr(treeChild(treeChild(real.r, "SVGModel"), "SVGContent"), "refid");
1000
+ const src = ref === undefined ? undefined : resources.get(ref);
1001
+ if (src === undefined) {
1002
+ return;
1003
+ }
1004
+ put("image", src);
1005
+ put("imageFit", "fill");
1006
+ put("imageClip", "none");
1007
+ }
1008
+
1009
+ /**
1010
+ * Reads one node realizer.
1011
+ * @param real - the realizer
1012
+ * @param put - receives the values
1013
+ * @param at - the sites
1014
+ * @param resources - the graph's shared pictures, for image and SVG nodes
1015
+ */
1016
+ function readNode(real: Realizer, put: PutValue, at: SiteOf, resources?: ReadonlyMap<string, string>): void {
1017
+ const { r } = real;
1018
+ readFill(real, put, at);
453
1019
  const border = treeChild(r, "BorderStyle");
454
1020
  if (border !== undefined) {
455
1021
  if (treeAttr(border, "hasColor") === "false") {
@@ -464,7 +1030,18 @@ function readNode(real: Realizer, put: PutValue, at: SiteOf): void {
464
1030
  put("width", canonNumber(treeAttr(geometry, "width"), at("width")));
465
1031
  put("height", canonNumber(treeAttr(geometry, "height"), at("height")));
466
1032
  put("shape", realizerShape(real, at));
467
- readLabels(treeChildren(r, "NodeLabel"), true, put, at);
1033
+ const points =
1034
+ real.type === "GenericNode" ? configurationOutline(treeAttr(r, "configuration") ?? "")?.points : undefined;
1035
+ if (points !== undefined) {
1036
+ put("shapePoints", points);
1037
+ }
1038
+ if (real.type === "TableNode") {
1039
+ readTable(real, put, at);
1040
+ }
1041
+ if (resources !== undefined && (real.type === "ImageNode" || real.type === "SVGNode")) {
1042
+ readPicture(real, resources, put);
1043
+ }
1044
+ readLabels(treeChildren(r, "NodeLabel"), true, put, at, geometry);
468
1045
  }
469
1046
 
470
1047
  /**
@@ -487,12 +1064,21 @@ function readEdge(real: Realizer, put: PutValue, at: SiteOf): void {
487
1064
  put("targetArrow", canonEnum("arrow", treeAttr(arrows, "target"), "yed", at("targetArrow")));
488
1065
  }
489
1066
  put("curved", edgeCurved(real));
1067
+ if (real.type === "ArcEdge") {
1068
+ // the bend yEd saves is the arc's apex, `y:Arc height` from the line between the ends (every yEd-saved arc
1069
+ // in the corpus: scala-collection-mutable, Animatron__player__flow), so the arc is the circle through it
1070
+ put("bendCurve", "arc");
1071
+ }
490
1072
  readLabels(treeChildren(r, "EdgeLabel"), false, put, at);
491
1073
  }
492
1074
 
493
1075
  /**
494
- * Whether yEd draws an edge curved: an arc always; a Bezier, quad curve, spline or generic edge only through its
495
- * control points (with none it is a straight line); a polyline only when it smooths bends it has.
1076
+ * Whether an edge is drawn curved through its bends: an arc always; a spline only through its control points (with
1077
+ * none it is a straight line); a polyline, and a generic edge (a framed or styled polyline), only when it smooths
1078
+ * bends it has. A quad curve edge never, nor a Bezier edge of whole cubic pieces (two control points, five, ...): its
1079
+ * curve is flattened into points on it (`readEdgeRoute`), drawn straight from one to the next, as a Graphviz spline
1080
+ * is; rounding their corners cut inside the curve (a quad curve of straightness 1, whose points are its control
1081
+ * polygon, was drawn bowed).
496
1082
  * @param real - the edge realizer
497
1083
  * @returns true when curved, null when a polyline does not say whether it smooths
498
1084
  */
@@ -500,8 +1086,16 @@ function edgeCurved(real: Realizer): boolean | null {
500
1086
  if (real.type === "ArcEdge") {
501
1087
  return true;
502
1088
  }
503
- const bent = treeChildren(treeChild(real.r, "Path"), "Point").length > 0;
504
- if (real.type !== "PolyLineEdge") {
1089
+ const points = treeChildren(treeChild(real.r, "Path"), "Point").length;
1090
+ if (real.type === "QuadCurveEdge") {
1091
+ return false;
1092
+ }
1093
+ if (real.type === "BezierEdge") {
1094
+ // a count of control points no run of cubic pieces takes is not flattened: its corners are rounded
1095
+ return points > 0 && (points + 1) % 3 !== 0;
1096
+ }
1097
+ const bent = points > 0;
1098
+ if (real.type !== "PolyLineEdge" && real.type !== "GenericEdge") {
505
1099
  return bent;
506
1100
  }
507
1101
  const smoothed = treeAttr(treeChild(real.r, "BendStyle"), "smoothed");
@@ -509,23 +1103,52 @@ function edgeCurved(real: Realizer): boolean | null {
509
1103
  }
510
1104
 
511
1105
  /**
512
- * An edge's bends: the points of its `y:Path`, relative to the centers of its two nodes. yEd draws a polyline through
513
- * them; a curve type (Bezier, quad curve, spline) passes near them as its control points.
1106
+ * An edge's route from its `y:Path`: the ports its ends attach at (`sx sy`, `tx ty`: offsets from the node centers),
1107
+ * relative to each node's size, and its bends, relative to the centers of its two nodes (a self-loop's to its node's
1108
+ * size). yEd draws a polyline, an arc or a spline through the points; a Bezier or quad curve edge takes them as
1109
+ * control points its curve does not pass through, so its curve is flattened into the points it does pass through.
514
1110
  * @param real - the edge realizer
515
- * @param centers - each node's center, x and y
1111
+ * @param nodes - each node's center x and y, width and height
516
1112
  * @param source - the source node's index
517
1113
  * @param target - the target node's index
518
- * @returns the `bends` value, or null without bends
1114
+ * @param put - receives the values
519
1115
  */
520
- function edgeBends(real: Realizer, centers: Float64Array, source: number, target: number): string | null {
521
- const points = treeChildren(treeChild(real.r, "Path"), "Point").map((p): BendPoint => [
1116
+ function readEdgeRoute(real: Realizer, nodes: Float64Array, source: number, target: number, put: PutValue): void {
1117
+ const path = treeChild(real.r, "Path");
1118
+ const at = (k: number): BendPoint => [nodes[4 * k], nodes[4 * k + 1]];
1119
+ const size = (k: number): BendPoint => [nodes[4 * k + 2], nodes[4 * k + 3]];
1120
+ const offset = (key: string): number => Number(treeAttr(path, key) ?? 0) || 0;
1121
+ const ends: readonly [BendPoint, BendPoint] = [
1122
+ [at(source)[0] + offset("sx"), at(source)[1] + offset("sy")],
1123
+ [at(target)[0] + offset("tx"), at(target)[1] + offset("ty")],
1124
+ ];
1125
+ const port = (k: number, end: BendPoint): string | null =>
1126
+ end[0] === at(k)[0] && end[1] === at(k)[1] ? null : canonNodeOffsets(at(k), size(k), [end], true);
1127
+ put("sourcePort", port(source, ends[0]));
1128
+ put("targetPort", port(target, ends[1]));
1129
+ let points = treeChildren(path, "Point").map((p): BendPoint => [
522
1130
  Number(treeAttr(p, "x")),
523
1131
  Number(treeAttr(p, "y")),
524
1132
  ]);
525
- const at = (k: number): BendPoint => [centers[2 * k], centers[2 * k + 1]];
526
- return canonBends(at(source), at(target), points, true);
1133
+ if (points.length > 0 && (real.type === "BezierEdge" || real.type === "QuadCurveEdge")) {
1134
+ const controls = [ends[0], ...points, ends[1]];
1135
+ const curve =
1136
+ real.type === "BezierEdge"
1137
+ ? flattenCubic(controls)
1138
+ : flattenQuadSpline(controls, Number(treeAttr(real.r, "straightness") ?? YED_STRAIGHTNESS));
1139
+ points = (curve ?? controls).slice(1, -1);
1140
+ }
1141
+ put(
1142
+ "bends",
1143
+ source === target
1144
+ ? canonNodeOffsets(at(source), size(source), points, true)
1145
+ : canonBends(at(source), at(target), points, true),
1146
+ );
527
1147
  }
528
1148
 
1149
+ /** yEd's quad curve straightness when a file gives none. */
1150
+ const YED_STRAIGHTNESS = 0.1;
1151
+
529
1152
  /** Canonical values per property, by element index. */
530
1153
  export type ValueColumns = Record<string, (StyleValue | null)[]>;
531
1154
 
@@ -567,8 +1190,9 @@ export interface YedRead {
567
1190
  */
568
1191
  export function readYedStyles(snapshot: GraphSnapshot, notes: StyleNotes, budget: StyleWorkBudget): YedRead | null {
569
1192
  let found = false;
570
- // each node's center, read with the node, for its edges' bends; NaN for a node without yEd graphics
571
- const centers = new Float64Array(2 * snapshot.nodeCount).fill(Number.NaN);
1193
+ const resources = yedResources(snapshot);
1194
+ // each node's center, width and height, read with the node, for its edges' routes; NaN without yEd graphics
1195
+ const boxes = new Float64Array(4 * snapshot.nodeCount).fill(Number.NaN);
572
1196
  const read = (target: StyleTarget): ValueColumns => {
573
1197
  const table = target === "node" ? snapshot.nodes : snapshot.edges;
574
1198
  const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
@@ -593,13 +1217,16 @@ export function readYedStyles(snapshot: GraphSnapshot, notes: StyleNotes, budget
593
1217
  out.put(i, property, value);
594
1218
  };
595
1219
  if (target === "node") {
596
- readNode(real, put, at);
1220
+ readNode(real, put, at, resources);
597
1221
  const geometry = treeChild(real.r, "Geometry");
598
- centers[2 * i] = Number(treeAttr(geometry, "x")) + Number(treeAttr(geometry, "width")) / 2;
599
- centers[2 * i + 1] = Number(treeAttr(geometry, "y")) + Number(treeAttr(geometry, "height")) / 2;
1222
+ const [w, h] = [Number(treeAttr(geometry, "width")), Number(treeAttr(geometry, "height"))];
1223
+ boxes.set(
1224
+ [Number(treeAttr(geometry, "x")) + w / 2, Number(treeAttr(geometry, "y")) + h / 2, w, h],
1225
+ 4 * i,
1226
+ );
600
1227
  } else {
601
1228
  readEdge(real, put, at);
602
- put("bends", edgeBends(real, centers, snapshot.edgeSource(i), snapshot.edgeTarget(i)));
1229
+ readEdgeRoute(real, boxes, snapshot.edgeSource(i), snapshot.edgeTarget(i), put);
603
1230
  }
604
1231
  }
605
1232
  return out.values;
@@ -617,9 +1244,12 @@ export function readYedStyles(snapshot: GraphSnapshot, notes: StyleNotes, budget
617
1244
  * @category Built-in formats
618
1245
  */
619
1246
  export const GRAPHML_STYLE_CAPABILITIES: StyleWriteCapabilities = Object.freeze({
1247
+ tool: "yed",
620
1248
  node: Object.freeze([
621
1249
  "fill",
622
1250
  "fillOpacity",
1251
+ "fillGradient",
1252
+ "fillGradientAngle",
623
1253
  "borderColor",
624
1254
  "borderWidth",
625
1255
  "borderStyle",
@@ -643,6 +1273,8 @@ export const GRAPHML_STYLE_CAPABILITIES: StyleWriteCapabilities = Object.freeze(
643
1273
  "targetArrow",
644
1274
  "curved",
645
1275
  "bends",
1276
+ "sourcePort",
1277
+ "targetPort",
646
1278
  "label",
647
1279
  "labelColor",
648
1280
  "labelSize",
@@ -696,17 +1328,21 @@ export const YED_ARROWS: ReadonlyMap<string, string> = new Map([
696
1328
  ["crow", "crows_foot_many"],
697
1329
  ]);
698
1330
 
699
- /** yEd's label positions in the internal model, by neutral position. */
1331
+ /** yEd's internal label model positions by neutral position: the center, and against a side or in a corner inside. */
1332
+ const INTERNAL_MODEL_POSITIONS: ReadonlyMap<string, string> = new Map(
1333
+ [...INTERNAL_POSITIONS].map(([model, position]) => [position, model]),
1334
+ );
1335
+
1336
+ /** yEd's eight-position label model positions by neutral position, all outside the node. */
700
1337
  const YED_MODEL_POSITIONS: ReadonlyMap<string, string> = new Map([
701
- ["center", "c"],
702
- ["top", "t"],
703
- ["bottom", "b"],
704
- ["left", "l"],
705
- ["right", "r"],
706
- ["top-left", "tl"],
707
- ["top-right", "tr"],
708
- ["bottom-left", "bl"],
709
- ["bottom-right", "br"],
1338
+ ["top", "n"],
1339
+ ["bottom", "s"],
1340
+ ["left", "w"],
1341
+ ["right", "e"],
1342
+ ["top-left", "nw"],
1343
+ ["top-right", "ne"],
1344
+ ["bottom-left", "sw"],
1345
+ ["bottom-right", "se"],
710
1346
  ]);
711
1347
 
712
1348
  /**
@@ -774,22 +1410,32 @@ export function yedSpelled(
774
1410
  /** One element's value of a property. */
775
1411
  type GetValue = (property: string) => StyleValue | null;
776
1412
 
1413
+ /** The Java logical font each family the reader gives one is written back as. */
1414
+ const JAVA_LOGICAL: Readonly<Record<string, string>> = {
1415
+ [JAVA_SANS]: "Dialog",
1416
+ [JAVA_SERIF]: "Serif",
1417
+ [JAVA_MONO]: "Monospaced",
1418
+ };
1419
+
777
1420
  /**
778
- * The label attributes and text of one element.
1421
+ * A CSS family as the one font name yEd reads: a Java logical font's family as that font, else the list's first name.
1422
+ * @param family - the CSS family or family list
1423
+ * @returns the font name
1424
+ */
1425
+ export function yedFontName(family: string): string {
1426
+ return Object.hasOwn(JAVA_LOGICAL, family) ? JAVA_LOGICAL[family] : family.split(",")[0].trim();
1427
+ }
1428
+
1429
+ /**
1430
+ * A label's font attributes: family, size and style.
779
1431
  * @param get - the element's values
780
- * @param node - whether it is a node label (which has a position)
781
- * @param approximate - records approximations
782
- * @returns the label element, or null when the element has no label text
1432
+ * @returns the label element holding them
783
1433
  */
784
- function labelTree(get: GetValue, node: boolean, approximate: Approximate): Tree | null {
785
- const text = get("label");
786
- if (typeof text !== "string" || text.trim().length === 0) {
787
- return null;
788
- }
1434
+ function labelFontTree(get: GetValue): Tree {
789
1435
  const label: Tree = {};
790
1436
  const font = get("labelFont");
791
1437
  if (typeof font === "string") {
792
- label["@_fontFamily"] = font;
1438
+ label["@_fontFamily"] = yedFontName(font);
793
1439
  }
794
1440
  const size = get("labelSize");
795
1441
  if (typeof size === "number") {
@@ -801,18 +1447,36 @@ function labelTree(get: GetValue, node: boolean, approximate: Approximate): Tree
801
1447
  const style = (weight === "bold" ? "bold" : "") + (italic === true ? "italic" : "");
802
1448
  label["@_fontStyle"] = style.length === 0 ? "plain" : style;
803
1449
  }
1450
+ return label;
1451
+ }
1452
+
1453
+ /**
1454
+ * The label attributes and text of one element.
1455
+ * @param get - the element's values
1456
+ * @param node - whether it is a node label (which has a position)
1457
+ * @param approximate - records approximations
1458
+ * @returns the label element, or null when the element has no label text
1459
+ */
1460
+ function labelTree(get: GetValue, node: boolean, approximate: Approximate): Tree | null {
1461
+ const text = get("label");
1462
+ if (typeof text !== "string" || text.trim().length === 0) {
1463
+ return null;
1464
+ }
1465
+ const label = labelFontTree(get);
804
1466
  const color = get("labelColor");
805
1467
  if (typeof color === "string") {
806
1468
  label["@_textColor"] = color.toUpperCase();
807
1469
  }
808
1470
  const position = node ? get("labelPosition") : null;
809
1471
  if (typeof position === "string") {
810
- const written = YED_MODEL_POSITIONS.get(position);
811
- if (written === undefined) {
1472
+ const inside = INTERNAL_MODEL_POSITIONS.get(position);
1473
+ const outside = YED_MODEL_POSITIONS.get(position);
1474
+ if (inside === undefined && outside === undefined) {
812
1475
  approximate("labelPosition", position);
813
1476
  }
814
- label["@_modelName"] = "internal";
815
- label["@_modelPosition"] = written ?? "c";
1477
+ // the center and the inside positions in yEd's internal model, the outside ones in its eight-position one
1478
+ label["@_modelName"] = outside === undefined ? "internal" : "eight_pos";
1479
+ label["@_modelPosition"] = outside ?? inside ?? "c";
816
1480
  }
817
1481
  label["#text"] = text;
818
1482
  return label;
@@ -832,6 +1496,14 @@ function shapeNodeTree(get: GetValue, at: readonly [string, string] | null, appr
832
1496
  const fillOpacity = get("fillOpacity");
833
1497
  if (typeof fill === "string") {
834
1498
  node["y:Fill"] = { "@_color": yedColor(fill, fillOpacity), "@_transparent": "false" };
1499
+ const second = get("fillGradient");
1500
+ if (typeof second === "string") {
1501
+ (node["y:Fill"] as Tree)["@_color2"] = second.toUpperCase();
1502
+ const angle = get("fillGradientAngle");
1503
+ if (angle !== YED_GRADIENT_ANGLE) {
1504
+ approximate("fillGradientAngle", angle ?? 0);
1505
+ }
1506
+ }
835
1507
  } else if (fillOpacity === 0) {
836
1508
  node["y:Fill"] = { "@_hasColor": "false", "@_transparent": "false" };
837
1509
  }
@@ -945,59 +1617,25 @@ function polyLineEdgeTree(get: GetValue, path: unknown, approximate: Approximate
945
1617
  return { "y:PolyLineEdge": edge };
946
1618
  }
947
1619
 
948
- /**
949
- * Each element's values of the properties the writer writes, as a getter per element.
950
- * @param picture - each element's value of a property
951
- * @param target - nodes or edges
952
- * @returns the getter
953
- */
954
- function getter(
955
- picture: (target: StyleTarget, property: string) => readonly (StyleValue | null)[],
956
- target: StyleTarget,
957
- ): (i: number) => GetValue {
958
- const columns = new Map<string, readonly (StyleValue | null)[]>();
959
- for (const p of GRAPHML_STYLE_CAPABILITIES[target]) {
960
- columns.set(p, picture(target, p));
961
- }
962
- return (i) => (property) => columns.get(property)?.[i] ?? null;
963
- }
964
-
965
1620
  /**
966
1621
  * For a file graphty wrote: where a value read from the yEd graphics is what the writer writes for the block's own
967
1622
  * value (a pentagon written as a hexagon, an opacity rounded to yEd's 255 steps), the block's exact value is the
968
1623
  * truth, so a re-import gives back the same rules; a value another program changed since stays the truth.
1624
+ * @param snapshot - the graph
1625
+ * @param text - the block's text
969
1626
  * @param read - the values the reader read, changed in place
970
- * @param picture - each element's value of a property under the block's rules
971
- * @param counts - the node and edge counts
972
- * @param counts.node - the node count
973
- * @param counts.edge - the edge count
974
- * @param notes - a scratch note list for reading back what the writer writes
975
1627
  */
976
- export function exactFromBlock(
977
- read: YedRead,
978
- picture: (target: StyleTarget, property: string) => readonly (StyleValue | null)[],
979
- counts: { readonly node: number; readonly edge: number },
980
- notes: StyleNotes,
981
- ): void {
982
- for (const target of ["node", "edge"] as const) {
983
- const values = read[target];
984
- const get = getter(picture, target);
985
- for (let i = 0; i < counts[target]; i++) {
986
- const want = get(i);
1628
+ export function exactFromBlock(snapshot: GraphSnapshot, text: string, read: YedRead): void {
1629
+ const notes = new StyleNotes();
1630
+ takeFromBlock(snapshot, text, "graphml", (target) => ({
1631
+ values: read[target],
1632
+ properties: GRAPHML_STYLE_CAPABILITIES[target],
1633
+ writes: GRAPHML_STYLE_CAPABILITIES[target],
1634
+ readBack: (_i, want) => {
987
1635
  const back = writtenAndReadBack(target, want, notes);
988
- if (back === null) {
989
- continue;
990
- }
991
- for (const property of GRAPHML_STYLE_CAPABILITIES[target]) {
992
- const native = values[property]?.[i] ?? null;
993
- const w = want(property);
994
- if (native !== w && native === (back.get(property) ?? null)) {
995
- values[property] ??= new Array<StyleValue | null>(counts[target]).fill(null);
996
- values[property][i] = w;
997
- }
998
- }
999
- }
1000
- }
1636
+ return back === null ? null : (property) => back.get(property) ?? null;
1637
+ },
1638
+ }));
1001
1639
  }
1002
1640
 
1003
1641
  /**
@@ -1109,25 +1747,44 @@ function keptPath(table: GraphSnapshot["edges"], columns: readonly string[], e:
1109
1747
  return undefined;
1110
1748
  }
1111
1749
 
1750
+ /** A written node's center and its width and height. */
1751
+ type WrittenBox = readonly [center: BendPoint, size: BendPoint];
1752
+
1112
1753
  /**
1113
- * An edge's `y:Path` with its points placed from its `bends` value between the written node centers, so the bends
1114
- * read back as written; the ports of the path it had are kept. Without a value, or without both centers, the path it
1115
- * had.
1754
+ * An edge's `y:Path` with its points placed from its `bends` value between the written node centers (a self-loop's
1755
+ * around its node) and its ports from its `sourcePort` and `targetPort`, so they read back as written; a port with no
1756
+ * value keeps the one of the path it had. Without a bend or port value, or without both centers, the path it had.
1116
1757
  * @param kept - the path from the graphics the edge had, or undefined
1117
- * @param bends - the edge's `bends` value
1118
- * @param ends - the written centers of its source and target
1758
+ * @param get - the edge's values
1759
+ * @param ends - the written boxes of its source and target
1760
+ * @param loop - whether the edge is a self-loop
1119
1761
  * @returns the path, or undefined
1120
1762
  */
1121
- function pathWithBends(kept: unknown, bends: StyleValue | null, ends: readonly [BendPoint, BendPoint]): unknown {
1122
- const points = typeof bends === "string" ? bendsToPoints(ends[0], ends[1], bends, true) : null;
1123
- if (points === null) {
1763
+ function pathWithRoute(kept: unknown, get: GetValue, ends: readonly [WrittenBox, WrittenBox], loop: boolean): unknown {
1764
+ const bends = get("bends");
1765
+ const [[c0, size0], [c1]] = ends;
1766
+ let points: BendPoint[] | null = null;
1767
+ if (typeof bends === "string") {
1768
+ points = loop ? nodeOffsetsToPoints(c0, size0, bends, true) : bendsToPoints(c0, c1, bends, true);
1769
+ }
1770
+ const ports = (["sourcePort", "targetPort"] as const).map((property, k) => {
1771
+ const value = get(property);
1772
+ const [center, size] = ends[k];
1773
+ const at = typeof value === "string" ? nodeOffsetsToPoints(center, size, value, true) : null;
1774
+ return at === null ? null : [at[0][0] - center[0], at[0][1] - center[1]];
1775
+ });
1776
+ if (points === null && ports.every((p) => p === null)) {
1124
1777
  return kept;
1125
1778
  }
1126
1779
  const path: Tree = {};
1127
- for (const port of ["sx", "sy", "tx", "ty"]) {
1128
- path[`@_${port}`] = treeAttr(kept, port) ?? "0.0";
1129
- }
1130
- path["y:Point"] = points.map(([x, y]) => ({ "@_x": String(x), "@_y": String(y) }));
1780
+ ["sx", "sy", "tx", "ty"].forEach((key, k) => {
1781
+ const port = ports[k >> 1];
1782
+ path[`@_${key}`] = port === null ? (treeAttr(kept, key) ?? "0.0") : String(port[k & 1]);
1783
+ });
1784
+ const written =
1785
+ points ??
1786
+ treeChildren(kept, "Point").map((q): BendPoint => [Number(treeAttr(q, "x")), Number(treeAttr(q, "y"))]);
1787
+ path["y:Point"] = written.map(([x, y]) => ({ "@_x": String(x), "@_y": String(y) }));
1131
1788
  return path;
1132
1789
  }
1133
1790
 
@@ -1173,27 +1830,32 @@ export function graphmlStyledExport(
1173
1830
  input.picture(target, property as never);
1174
1831
  const nodeColumns = treeColumns(snapshot.nodes);
1175
1832
  const edgeColumns = treeColumns(snapshot.edges);
1176
- const getNode = getter(picture, "node");
1177
- const getEdge = getter(picture, "edge");
1833
+ const getNode = elementValues(picture, "node", GRAPHML_STYLE_CAPABILITIES.node);
1834
+ const getEdge = elementValues(picture, "edge", GRAPHML_STYLE_CAPABILITIES.edge);
1178
1835
  const nodeTrees: (Tree | null)[] = [];
1179
1836
  for (let i = 0; i < snapshot.nodeCount; i++) {
1180
1837
  const get = getNode(i);
1181
1838
  const at = keptPosition(snapshot.nodes, nodeColumns, i) ?? columnPosition(snapshot, i, get);
1182
1839
  nodeTrees.push(shapeNodeTree(get, at, approximateFor("node")));
1183
1840
  }
1184
- const centers = nodeTrees.map((tree): BendPoint => {
1841
+ const boxes = nodeTrees.map((tree): WrittenBox => {
1185
1842
  const geometry = treeChild(treeChild(tree, "ShapeNode"), "Geometry");
1186
1843
  const at = (k: string): number => Number(treeAttr(geometry, k) ?? Number.NaN);
1187
- return [at("x") + at("width") / 2, at("y") + at("height") / 2];
1844
+ return [
1845
+ [at("x") + at("width") / 2, at("y") + at("height") / 2],
1846
+ [at("width"), at("height")],
1847
+ ];
1188
1848
  });
1189
1849
  const edgeTrees: (Tree | null)[] = [];
1190
1850
  for (let e = 0; e < snapshot.edgeCount; e++) {
1191
1851
  const get = getEdge(e);
1192
- const ends: readonly [BendPoint, BendPoint] = [
1193
- centers[snapshot.edgeSource(e)],
1194
- centers[snapshot.edgeTarget(e)],
1195
- ];
1196
- const path = pathWithBends(keptPath(snapshot.edges, edgeColumns, e), get("bends"), ends);
1852
+ const [source, target] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
1853
+ const path = pathWithRoute(
1854
+ keptPath(snapshot.edges, edgeColumns, e),
1855
+ get,
1856
+ [boxes[source], boxes[target]],
1857
+ source === target,
1858
+ );
1197
1859
  edgeTrees.push(polyLineEdgeTree(get, path, approximateFor("edge")));
1198
1860
  }
1199
1861
  const out = snapshot.withColumns();