@graphty/graph-io 0.3.48 → 0.3.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (570) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-Bzn3L-je.js.map} +1 -1
  3. package/dist/chunks/bends-BGXjv_U4.js +129 -0
  4. package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
  5. package/dist/chunks/{block-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
  6. package/dist/chunks/block-iptrlMBb.js.map +1 -0
  7. package/dist/chunks/choose-CczZJaX_.js +717 -0
  8. package/dist/chunks/choose-CczZJaX_.js.map +1 -0
  9. package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
  15. package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
  16. package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
  17. package/dist/chunks/{credentials-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
  18. package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
  19. package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
  20. package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
  24. package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
  26. package/dist/chunks/emit-BwHQkZle.js.map +1 -0
  27. package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
  28. package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
  29. package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
  30. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  31. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  32. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  33. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
  34. package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
  35. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
  36. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
  39. package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
  40. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-nDfxIK5D.js.map} +1 -1
  41. package/dist/chunks/format-BXiAb-1h.js +408 -0
  42. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  43. package/dist/chunks/{generic-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
  44. package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
  45. package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
  46. package/dist/chunks/importer-B92x1xY5.js.map +1 -0
  47. package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
  48. package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
  49. package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
  50. package/dist/chunks/importer-DaLTjbds.js.map +1 -0
  51. package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
  52. package/dist/chunks/importer-GREKMdIf.js.map +1 -0
  53. package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
  54. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
  55. package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
  56. package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
  57. package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
  58. package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
  59. package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
  60. package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
  61. package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
  62. package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  63. package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
  64. package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
  65. package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
  66. package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  67. package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
  68. package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
  69. package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
  70. package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
  71. package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
  72. package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
  74. package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
  76. package/dist/chunks/styles-CCs214_3.js.map +1 -0
  77. package/dist/chunks/styles-Cm62yyQX.js +2812 -0
  78. package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
  79. package/dist/chunks/styles-DPQQIig4.js +1928 -0
  80. package/dist/chunks/styles-DPQQIig4.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
  82. package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
  83. package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
  84. package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
  85. package/dist/csv.js +7 -7
  86. package/dist/cx.js +2 -2
  87. package/dist/cx2.js +2 -2
  88. package/dist/cys.js +1 -1
  89. package/dist/dot.js +5 -4
  90. package/dist/dot.js.map +1 -1
  91. package/dist/gexf.js +42 -12
  92. package/dist/gexf.js.map +1 -1
  93. package/dist/gml.js +847 -193
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +232 -220
  96. package/dist/graph-io.js.map +1 -1
  97. package/dist/graphml.js +3 -3
  98. package/dist/json.js +3 -2
  99. package/dist/neo4j.js +6 -6
  100. package/dist/obo.js +1 -1
  101. package/dist/pajek.js +1 -1
  102. package/dist/positions.js +45 -3
  103. package/dist/positions.js.map +1 -1
  104. package/dist/sources-cypher.js +138 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +16 -6
  108. package/dist/sources-rest.js.map +1 -1
  109. package/dist/sources-sparql.d.ts +1 -0
  110. package/dist/sources-sparql.js +405 -0
  111. package/dist/sources-sparql.js.map +1 -0
  112. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  113. package/dist/src/formats/cx/importer.js +5 -1
  114. package/dist/src/formats/cx/importer.js.map +1 -1
  115. package/dist/src/formats/cx/styles.d.ts +24 -1
  116. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  117. package/dist/src/formats/cx/styles.js +117 -11
  118. package/dist/src/formats/cx/styles.js.map +1 -1
  119. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  120. package/dist/src/formats/cx2/importer.js +1 -0
  121. package/dist/src/formats/cx2/importer.js.map +1 -1
  122. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  123. package/dist/src/formats/cx2/styles.js +3 -1
  124. package/dist/src/formats/cx2/styles.js.map +1 -1
  125. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cys/importer.js +1 -0
  127. package/dist/src/formats/cys/importer.js.map +1 -1
  128. package/dist/src/formats/cys/styles.d.ts +2 -0
  129. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cys/styles.js +15 -7
  131. package/dist/src/formats/cys/styles.js.map +1 -1
  132. package/dist/src/formats/dot/drawing.d.ts +98 -0
  133. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  134. package/dist/src/formats/dot/drawing.js +734 -0
  135. package/dist/src/formats/dot/drawing.js.map +1 -0
  136. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  137. package/dist/src/formats/dot/importer.js +108 -31
  138. package/dist/src/formats/dot/importer.js.map +1 -1
  139. package/dist/src/formats/dot/label-places.d.ts +34 -0
  140. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  141. package/dist/src/formats/dot/label-places.js +179 -0
  142. package/dist/src/formats/dot/label-places.js.map +1 -0
  143. package/dist/src/formats/dot/record.d.ts +50 -0
  144. package/dist/src/formats/dot/record.d.ts.map +1 -0
  145. package/dist/src/formats/dot/record.js +275 -0
  146. package/dist/src/formats/dot/record.js.map +1 -0
  147. package/dist/src/formats/dot/styles.d.ts +62 -2
  148. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  149. package/dist/src/formats/dot/styles.js +1454 -119
  150. package/dist/src/formats/dot/styles.js.map +1 -1
  151. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  152. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  153. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  154. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  155. package/dist/src/formats/gexf/importer.d.ts +7 -0
  156. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  157. package/dist/src/formats/gexf/importer.js +41 -5
  158. package/dist/src/formats/gexf/importer.js.map +1 -1
  159. package/dist/src/formats/gexf/preview.d.ts +77 -0
  160. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  161. package/dist/src/formats/gexf/preview.js +191 -0
  162. package/dist/src/formats/gexf/preview.js.map +1 -0
  163. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  164. package/dist/src/formats/gexf/schema.js +2 -1
  165. package/dist/src/formats/gexf/schema.js.map +1 -1
  166. package/dist/src/formats/gexf/styles.d.ts +58 -31
  167. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  168. package/dist/src/formats/gexf/styles.js +848 -225
  169. package/dist/src/formats/gexf/styles.js.map +1 -1
  170. package/dist/src/formats/gml/importer.d.ts +5 -2
  171. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  172. package/dist/src/formats/gml/importer.js +258 -71
  173. package/dist/src/formats/gml/importer.js.map +1 -1
  174. package/dist/src/formats/gml/index.d.ts +1 -1
  175. package/dist/src/formats/gml/index.d.ts.map +1 -1
  176. package/dist/src/formats/gml/index.js +1 -1
  177. package/dist/src/formats/gml/index.js.map +1 -1
  178. package/dist/src/formats/gml/positions.d.ts +7 -0
  179. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  180. package/dist/src/formats/gml/positions.js +29 -7
  181. package/dist/src/formats/gml/positions.js.map +1 -1
  182. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  183. package/dist/src/formats/gml/styles.js +753 -101
  184. package/dist/src/formats/gml/styles.js.map +1 -1
  185. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  186. package/dist/src/formats/graphml/styles-plain.js +6 -10
  187. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  188. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  189. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  190. package/dist/src/formats/graphml/styles-yed.js +692 -161
  191. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  192. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  193. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  194. package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
  195. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  196. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  197. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/yfiles.js +16 -6
  199. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  200. package/dist/src/formats/json/dialect.d.ts +3 -2
  201. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  202. package/dist/src/formats/json/dialect.js +39 -5
  203. package/dist/src/formats/json/dialect.js.map +1 -1
  204. package/dist/src/formats/json/importer.d.ts +13 -2
  205. package/dist/src/formats/json/importer.d.ts.map +1 -1
  206. package/dist/src/formats/json/importer.js +42 -6
  207. package/dist/src/formats/json/importer.js.map +1 -1
  208. package/dist/src/formats/json/index.d.ts +1 -1
  209. package/dist/src/formats/json/index.d.ts.map +1 -1
  210. package/dist/src/formats/json/index.js +1 -1
  211. package/dist/src/formats/json/index.js.map +1 -1
  212. package/dist/src/formats/json/positions.d.ts +5 -2
  213. package/dist/src/formats/json/positions.d.ts.map +1 -1
  214. package/dist/src/formats/json/positions.js +20 -4
  215. package/dist/src/formats/json/positions.js.map +1 -1
  216. package/dist/src/formats/json/styles.d.ts +12 -1
  217. package/dist/src/formats/json/styles.d.ts.map +1 -1
  218. package/dist/src/formats/json/styles.js +1755 -136
  219. package/dist/src/formats/json/styles.js.map +1 -1
  220. package/dist/src/formats/pajek/draw.d.ts +96 -0
  221. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  222. package/dist/src/formats/pajek/draw.js +372 -0
  223. package/dist/src/formats/pajek/draw.js.map +1 -0
  224. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  225. package/dist/src/formats/pajek/exporter.js +70 -51
  226. package/dist/src/formats/pajek/exporter.js.map +1 -1
  227. package/dist/src/formats/pajek/importer.d.ts +9 -0
  228. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  229. package/dist/src/formats/pajek/importer.js +233 -102
  230. package/dist/src/formats/pajek/importer.js.map +1 -1
  231. package/dist/src/formats/pajek/index.d.ts +1 -0
  232. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  233. package/dist/src/formats/pajek/index.js.map +1 -1
  234. package/dist/src/formats/pajek/styles.d.ts +15 -7
  235. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  236. package/dist/src/formats/pajek/styles.js +1278 -114
  237. package/dist/src/formats/pajek/styles.js.map +1 -1
  238. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  239. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  240. package/dist/src/formats/pajek/syntax.js +26 -2
  241. package/dist/src/formats/pajek/syntax.js.map +1 -1
  242. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  243. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  244. package/dist/src/formats/xgmml/emit.js +65 -5
  245. package/dist/src/formats/xgmml/emit.js.map +1 -1
  246. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  247. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  248. package/dist/src/formats/xgmml/styles.js +277 -60
  249. package/dist/src/formats/xgmml/styles.js.map +1 -1
  250. package/dist/src/index.d.ts +4 -3
  251. package/dist/src/index.d.ts.map +1 -1
  252. package/dist/src/index.js +4 -3
  253. package/dist/src/index.js.map +1 -1
  254. package/dist/src/positions/convert.d.ts.map +1 -1
  255. package/dist/src/positions/convert.js +11 -1
  256. package/dist/src/positions/convert.js.map +1 -1
  257. package/dist/src/positions/extract.d.ts.map +1 -1
  258. package/dist/src/positions/extract.js +53 -1
  259. package/dist/src/positions/extract.js.map +1 -1
  260. package/dist/src/positions/index.d.ts +1 -1
  261. package/dist/src/positions/index.d.ts.map +1 -1
  262. package/dist/src/positions/types.d.ts +59 -0
  263. package/dist/src/positions/types.d.ts.map +1 -1
  264. package/dist/src/sources/builtins.d.ts +1 -1
  265. package/dist/src/sources/builtins.d.ts.map +1 -1
  266. package/dist/src/sources/builtins.js +8 -2
  267. package/dist/src/sources/builtins.js.map +1 -1
  268. package/dist/src/sources/context.d.ts.map +1 -1
  269. package/dist/src/sources/context.js +1 -0
  270. package/dist/src/sources/context.js.map +1 -1
  271. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  272. package/dist/src/sources/cypher/descriptor.js +5 -0
  273. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  274. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  275. package/dist/src/sources/cypher/index.js +124 -18
  276. package/dist/src/sources/cypher/index.js.map +1 -1
  277. package/dist/src/sources/cypher/params.d.ts +1 -1
  278. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  279. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  280. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  281. package/dist/src/sources/cypher/query-builder.js +31 -0
  282. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  283. package/dist/src/sources/ids.d.ts +5 -0
  284. package/dist/src/sources/ids.d.ts.map +1 -1
  285. package/dist/src/sources/ids.js +5 -0
  286. package/dist/src/sources/ids.js.map +1 -1
  287. package/dist/src/sources/params.d.ts +3 -0
  288. package/dist/src/sources/params.d.ts.map +1 -1
  289. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  290. package/dist/src/sources/rest/descriptor.js +5 -0
  291. package/dist/src/sources/rest/descriptor.js.map +1 -1
  292. package/dist/src/sources/rest/source.d.ts.map +1 -1
  293. package/dist/src/sources/rest/source.js +15 -0
  294. package/dist/src/sources/rest/source.js.map +1 -1
  295. package/dist/src/sources/sigv4.d.ts +5 -3
  296. package/dist/src/sources/sigv4.d.ts.map +1 -1
  297. package/dist/src/sources/sigv4.js +6 -4
  298. package/dist/src/sources/sigv4.js.map +1 -1
  299. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  300. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  301. package/dist/src/sources/sparql/descriptor.js +64 -0
  302. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  303. package/dist/src/sources/sparql/index.d.ts +28 -0
  304. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  305. package/dist/src/sources/sparql/index.js +314 -0
  306. package/dist/src/sources/sparql/index.js.map +1 -0
  307. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  308. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  309. package/dist/src/sources/sparql/ntriples.js +180 -0
  310. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  311. package/dist/src/sources/sparql/params.d.ts +27 -0
  312. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  313. package/dist/src/sources/sparql/params.js +5 -0
  314. package/dist/src/sources/sparql/params.js.map +1 -0
  315. package/dist/src/sources/sparql/query.d.ts +72 -0
  316. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  317. package/dist/src/sources/sparql/query.js +113 -0
  318. package/dist/src/sources/sparql/query.js.map +1 -0
  319. package/dist/src/sources/types.d.ts +31 -0
  320. package/dist/src/sources/types.d.ts.map +1 -1
  321. package/dist/src/styles/annotations.d.ts +61 -5
  322. package/dist/src/styles/annotations.d.ts.map +1 -1
  323. package/dist/src/styles/annotations.js +130 -22
  324. package/dist/src/styles/annotations.js.map +1 -1
  325. package/dist/src/styles/canon/bends.d.ts +46 -0
  326. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  327. package/dist/src/styles/canon/bends.js +123 -0
  328. package/dist/src/styles/canon/bends.js.map +1 -1
  329. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  330. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  331. package/dist/src/styles/canon/color-tables.js +10 -4
  332. package/dist/src/styles/canon/color-tables.js.map +1 -1
  333. package/dist/src/styles/canon/color.d.ts +3 -1
  334. package/dist/src/styles/canon/color.d.ts.map +1 -1
  335. package/dist/src/styles/canon/color.js +103 -3
  336. package/dist/src/styles/canon/color.js.map +1 -1
  337. package/dist/src/styles/canon/enums.d.ts +2 -2
  338. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  339. package/dist/src/styles/canon/enums.js +81 -7
  340. package/dist/src/styles/canon/enums.js.map +1 -1
  341. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  342. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  343. package/dist/src/styles/canon/graphviz.js +57 -9
  344. package/dist/src/styles/canon/graphviz.js.map +1 -1
  345. package/dist/src/styles/canon/number.d.ts +8 -0
  346. package/dist/src/styles/canon/number.d.ts.map +1 -1
  347. package/dist/src/styles/canon/number.js +18 -0
  348. package/dist/src/styles/canon/number.js.map +1 -1
  349. package/dist/src/styles/canon/text.d.ts +29 -2
  350. package/dist/src/styles/canon/text.d.ts.map +1 -1
  351. package/dist/src/styles/canon/text.js +156 -16
  352. package/dist/src/styles/canon/text.js.map +1 -1
  353. package/dist/src/styles/codes.d.ts +2 -0
  354. package/dist/src/styles/codes.d.ts.map +1 -1
  355. package/dist/src/styles/codes.js +2 -0
  356. package/dist/src/styles/codes.js.map +1 -1
  357. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  358. package/dist/src/styles/cyjs/cascade.js +1015 -79
  359. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  360. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  361. package/dist/src/styles/cyjs/defaults-table.js +3 -0
  362. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  363. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  364. package/dist/src/styles/cyjs/emit.js +202 -9
  365. package/dist/src/styles/cyjs/emit.js.map +1 -1
  366. package/dist/src/styles/cyjs/face.d.ts +20 -0
  367. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  368. package/dist/src/styles/cyjs/face.js +332 -0
  369. package/dist/src/styles/cyjs/face.js.map +1 -0
  370. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  371. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  372. package/dist/src/styles/cyjs/mappers.js +461 -26
  373. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  374. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  375. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  376. package/dist/src/styles/cyjs/routes.js +360 -0
  377. package/dist/src/styles/cyjs/routes.js.map +1 -0
  378. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  379. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  380. package/dist/src/styles/cytoscape/charts.js +560 -0
  381. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  382. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  383. package/dist/src/styles/cytoscape/emit.js +156 -48
  384. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  385. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  386. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  387. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  388. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  389. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  390. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  391. package/dist/src/styles/cytoscape/mappings.js +92 -0
  392. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  393. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  394. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  395. package/dist/src/styles/cytoscape/resolve.js +623 -17
  396. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  397. package/dist/src/styles/defaults.d.ts +46 -26
  398. package/dist/src/styles/defaults.d.ts.map +1 -1
  399. package/dist/src/styles/defaults.js +308 -71
  400. package/dist/src/styles/defaults.js.map +1 -1
  401. package/dist/src/styles/index.d.ts +4 -3
  402. package/dist/src/styles/index.d.ts.map +1 -1
  403. package/dist/src/styles/index.js +3 -2
  404. package/dist/src/styles/index.js.map +1 -1
  405. package/dist/src/styles/internal.d.ts +1 -0
  406. package/dist/src/styles/internal.d.ts.map +1 -1
  407. package/dist/src/styles/internal.js +1 -0
  408. package/dist/src/styles/internal.js.map +1 -1
  409. package/dist/src/styles/io/generic.d.ts.map +1 -1
  410. package/dist/src/styles/io/generic.js +56 -16
  411. package/dist/src/styles/io/generic.js.map +1 -1
  412. package/dist/src/styles/io/round-trip.d.ts +56 -0
  413. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  414. package/dist/src/styles/io/round-trip.js +138 -0
  415. package/dist/src/styles/io/round-trip.js.map +1 -0
  416. package/dist/src/styles/io/writer.d.ts.map +1 -1
  417. package/dist/src/styles/io/writer.js +6 -1
  418. package/dist/src/styles/io/writer.js.map +1 -1
  419. package/dist/src/styles/notes.d.ts.map +1 -1
  420. package/dist/src/styles/notes.js +1 -0
  421. package/dist/src/styles/notes.js.map +1 -1
  422. package/dist/src/styles/plan/features.d.ts +1 -1
  423. package/dist/src/styles/plan/features.d.ts.map +1 -1
  424. package/dist/src/styles/plan/features.js +22 -2
  425. package/dist/src/styles/plan/features.js.map +1 -1
  426. package/dist/src/styles/plan/index.d.ts +1 -1
  427. package/dist/src/styles/plan/index.d.ts.map +1 -1
  428. package/dist/src/styles/plan/index.js +1 -1
  429. package/dist/src/styles/plan/index.js.map +1 -1
  430. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  431. package/dist/src/styles/plan/plan.js +61 -4
  432. package/dist/src/styles/plan/plan.js.map +1 -1
  433. package/dist/src/styles/plan/resolve.d.ts +11 -0
  434. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  435. package/dist/src/styles/plan/resolve.js +40 -4
  436. package/dist/src/styles/plan/resolve.js.map +1 -1
  437. package/dist/src/styles/slots.d.ts +14 -0
  438. package/dist/src/styles/slots.d.ts.map +1 -0
  439. package/dist/src/styles/slots.js +20 -0
  440. package/dist/src/styles/slots.js.map +1 -0
  441. package/dist/src/styles/types.d.ts +622 -6
  442. package/dist/src/styles/types.d.ts.map +1 -1
  443. package/dist/src/styles/vocabulary.d.ts +3 -2
  444. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  445. package/dist/src/styles/vocabulary.js +203 -0
  446. package/dist/src/styles/vocabulary.js.map +1 -1
  447. package/dist/styles.js +30 -239
  448. package/dist/styles.js.map +1 -1
  449. package/dist/xgmml.js +3 -3
  450. package/package.json +27 -7
  451. package/src/formats/cx/importer.ts +6 -1
  452. package/src/formats/cx/styles.ts +143 -9
  453. package/src/formats/cx2/importer.ts +1 -0
  454. package/src/formats/cx2/styles.ts +3 -1
  455. package/src/formats/cys/importer.ts +1 -0
  456. package/src/formats/cys/styles.ts +27 -5
  457. package/src/formats/dot/drawing.ts +799 -0
  458. package/src/formats/dot/importer.ts +120 -35
  459. package/src/formats/dot/label-places.ts +228 -0
  460. package/src/formats/dot/record.ts +336 -0
  461. package/src/formats/dot/styles.ts +1654 -153
  462. package/src/formats/gexf/dialog-metrics.ts +61 -0
  463. package/src/formats/gexf/importer.ts +50 -5
  464. package/src/formats/gexf/preview.ts +217 -0
  465. package/src/formats/gexf/schema.ts +2 -1
  466. package/src/formats/gexf/styles.ts +1099 -245
  467. package/src/formats/gml/importer.ts +291 -76
  468. package/src/formats/gml/index.ts +1 -1
  469. package/src/formats/gml/positions.ts +29 -7
  470. package/src/formats/gml/styles.ts +851 -109
  471. package/src/formats/graphml/styles-plain.ts +6 -15
  472. package/src/formats/graphml/styles-yed.ts +762 -173
  473. package/src/formats/graphml/styles-yfiles3.ts +485 -63
  474. package/src/formats/graphml/yfiles.ts +19 -6
  475. package/src/formats/json/dialect.ts +41 -5
  476. package/src/formats/json/importer.ts +59 -7
  477. package/src/formats/json/index.ts +1 -0
  478. package/src/formats/json/positions.ts +22 -5
  479. package/src/formats/json/styles.ts +2041 -185
  480. package/src/formats/pajek/draw.ts +458 -0
  481. package/src/formats/pajek/exporter.ts +81 -49
  482. package/src/formats/pajek/importer.ts +278 -103
  483. package/src/formats/pajek/index.ts +1 -0
  484. package/src/formats/pajek/styles.ts +1381 -133
  485. package/src/formats/pajek/syntax.ts +27 -2
  486. package/src/formats/xgmml/emit.ts +73 -5
  487. package/src/formats/xgmml/styles.ts +330 -71
  488. package/src/index.ts +5 -1
  489. package/src/positions/convert.ts +12 -1
  490. package/src/positions/extract.ts +55 -1
  491. package/src/positions/index.ts +1 -0
  492. package/src/positions/types.ts +60 -0
  493. package/src/sources/builtins.ts +8 -1
  494. package/src/sources/context.ts +1 -0
  495. package/src/sources/cypher/descriptor.ts +7 -1
  496. package/src/sources/cypher/index.ts +148 -18
  497. package/src/sources/cypher/params.ts +1 -1
  498. package/src/sources/cypher/query-builder.ts +33 -0
  499. package/src/sources/ids.ts +6 -0
  500. package/src/sources/params.ts +3 -0
  501. package/src/sources/rest/descriptor.ts +5 -0
  502. package/src/sources/rest/source.ts +16 -0
  503. package/src/sources/sigv4.ts +6 -4
  504. package/src/sources/sparql/descriptor.ts +67 -0
  505. package/src/sources/sparql/index.ts +356 -0
  506. package/src/sources/sparql/ntriples.ts +219 -0
  507. package/src/sources/sparql/params.ts +28 -0
  508. package/src/sources/sparql/query.ts +162 -0
  509. package/src/sources/types.ts +35 -0
  510. package/src/styles/annotations.ts +201 -27
  511. package/src/styles/canon/bends.ts +137 -0
  512. package/src/styles/canon/color-tables.ts +10 -4
  513. package/src/styles/canon/color.ts +105 -3
  514. package/src/styles/canon/enums.ts +98 -8
  515. package/src/styles/canon/graphviz.ts +71 -10
  516. package/src/styles/canon/number.ts +19 -0
  517. package/src/styles/canon/text.ts +187 -16
  518. package/src/styles/codes.ts +2 -0
  519. package/src/styles/cyjs/cascade.ts +1160 -84
  520. package/src/styles/cyjs/defaults-table.ts +3 -0
  521. package/src/styles/cyjs/emit.ts +233 -13
  522. package/src/styles/cyjs/face.ts +372 -0
  523. package/src/styles/cyjs/mappers.ts +492 -27
  524. package/src/styles/cyjs/routes.ts +432 -0
  525. package/src/styles/cytoscape/charts.ts +684 -0
  526. package/src/styles/cytoscape/emit.ts +170 -48
  527. package/src/styles/cytoscape/lexicon.ts +431 -78
  528. package/src/styles/cytoscape/mappings.ts +108 -0
  529. package/src/styles/cytoscape/resolve.ts +741 -17
  530. package/src/styles/defaults.ts +417 -108
  531. package/src/styles/index.ts +5 -0
  532. package/src/styles/internal.ts +1 -0
  533. package/src/styles/io/generic.ts +79 -23
  534. package/src/styles/io/round-trip.ts +202 -0
  535. package/src/styles/io/writer.ts +6 -1
  536. package/src/styles/notes.ts +1 -0
  537. package/src/styles/plan/features.ts +23 -2
  538. package/src/styles/plan/index.ts +1 -1
  539. package/src/styles/plan/plan.ts +69 -5
  540. package/src/styles/plan/resolve.ts +47 -4
  541. package/src/styles/slots.ts +25 -0
  542. package/src/styles/types.ts +633 -5
  543. package/src/styles/vocabulary.ts +211 -2
  544. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  545. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  546. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  547. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  548. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  549. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  550. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  551. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  552. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  553. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  554. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  555. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  556. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  557. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  558. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  559. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  560. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  561. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  562. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  563. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  564. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  565. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  566. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  567. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  568. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  569. package/dist/chunks/writer-DvHTl36J.js +0 -449
  570. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -264,6 +264,29 @@ const CLUSTER_PREFIX = "cluster";
264
264
  const CLUSTER_ATTRIBUTE = "cluster";
265
265
  const STATEMENTS_PER_ABORT_CHECK = 64;
266
266
  const MAX_ANCESTOR_WALK = 4096;
267
+ /**
268
+ * The graph attributes a cluster takes from the graphs around it when it sets none of its own: Graphviz gives a
269
+ * subgraph every graph attribute its enclosing graphs set before it opened (a root `label` set first labels every
270
+ * cluster). Only the attributes that decide how a cluster is drawn are copied.
271
+ */
272
+ const INHERITED_GRAPH_ATTRIBUTES: ReadonlySet<string> = new Set([
273
+ "bgcolor",
274
+ "color",
275
+ "colorscheme",
276
+ "fillcolor",
277
+ "fontcolor",
278
+ "fontname",
279
+ "fontsize",
280
+ "gradientangle",
281
+ "label",
282
+ "labeljust",
283
+ "labelloc",
284
+ "pencolor",
285
+ "penwidth",
286
+ "peripheries",
287
+ "style",
288
+ "tooltip",
289
+ ]);
267
290
 
268
291
  /**
269
292
  * The header keyword, ended by what may follow it in DOT: space, `{`, a quoted ID or a comment.
@@ -320,6 +343,8 @@ interface Scope {
320
343
  readonly containers: number[];
321
344
  /** Subgraph attributes buffered until the subgraph closes (the root applies them at once). */
322
345
  readonly attributes: Map<string, DotAttribute>;
346
+ /** The drawing attributes a cluster opened in this scope inherits: the enclosing scopes' and this one's so far. */
347
+ readonly graphDefaults: Map<string, DotAttribute>;
323
348
  /** Whether the subgraph is a cluster (by name or by `cluster=true`). */
324
349
  cluster: boolean;
325
350
  /** The container node index once created, or INVALID_INDEX. */
@@ -734,6 +759,12 @@ class DotParser {
734
759
  /** The parent assigned to a node by this import. */
735
760
  private readonly parentOf = new Map<number, number>();
736
761
 
762
+ /** Each cluster container's inherited drawing attributes, as its scope saw them when the cluster first opened. */
763
+ private readonly inherited = new Map<number, Map<string, DotAttribute>>();
764
+
765
+ /** The attributes each cluster container sets itself, which its inherited ones never replace. */
766
+ private readonly ownAttributes = new Map<number, Set<string>>();
767
+
737
768
  /** Nodes already warned about a cluster conflict. */
738
769
  private readonly conflictWarned = new Set<number>();
739
770
 
@@ -851,6 +882,7 @@ class DotParser {
851
882
  });
852
883
  const root = this.newScope(null, headerLine, true, null);
853
884
  this.statementList(root);
885
+ this.applyInherited();
854
886
  return lexer.next();
855
887
  }
856
888
 
@@ -873,6 +905,7 @@ class DotParser {
873
905
  memberSet: new Set(),
874
906
  containers: [],
875
907
  attributes: new Map(),
908
+ graphDefaults: new Map(parent?.graphDefaults),
876
909
  cluster: false,
877
910
  container: INVALID_INDEX,
878
911
  };
@@ -1113,42 +1146,10 @@ class DotParser {
1113
1146
  */
1114
1147
  private closeScope(scope: Scope, parent: Scope): void {
1115
1148
  const { container } = scope;
1116
- if (container !== INVALID_INDEX) {
1117
- for (const attribute of scope.attributes.values()) {
1118
- if (attribute.name !== CLUSTER_ATTRIBUTE) {
1119
- this.setNodeAttribute(container, attribute.name, attribute.value, attribute.line);
1120
- }
1121
- }
1122
- for (const nested of scope.containers) {
1123
- if (nested !== container && !this.parentOf.has(nested)) {
1124
- this.setParent(nested, container);
1125
- }
1126
- }
1127
- for (const member of scope.members) {
1128
- if (member === container) {
1129
- continue;
1130
- }
1131
- const existing = this.parentOf.get(member);
1132
- if (existing === undefined) {
1133
- this.setParent(member, container);
1134
- } else if (existing !== container && !this.isAncestor(container, existing)) {
1135
- this.clusterConflict(member, existing, container, scope.line);
1136
- }
1137
- }
1138
- parent.containers.push(container);
1149
+ if (container === INVALID_INDEX) {
1150
+ this.closePlainSubgraph(scope, parent);
1139
1151
  } else {
1140
- if (scope.attributes.size > 0) {
1141
- const names = [...scope.attributes.keys()].join(", ");
1142
- this.report.warning(
1143
- "unsupported",
1144
- DOT_ISSUE.SUBGRAPH_ATTRIBUTES_DROPPED,
1145
- `subgraph ${scope.name === null ? "(anonymous)" : JSON.stringify(scope.name)} is not a cluster; its attributes (${names}) cannot be represented and were dropped`,
1146
- { line: scope.line, element: scope.name },
1147
- );
1148
- }
1149
- for (const nested of scope.containers) {
1150
- parent.containers.push(nested);
1151
- }
1152
+ this.closeCluster(scope, parent, container);
1152
1153
  }
1153
1154
  if (!parent.root) {
1154
1155
  for (const member of scope.members) {
@@ -1160,6 +1161,86 @@ class DotParser {
1160
1161
  }
1161
1162
  }
1162
1163
 
1164
+ /**
1165
+ * Finish a cluster: apply its attributes to its container node, assign parents to its nested
1166
+ * containers and its members, and hand the container to the enclosing scope.
1167
+ * @param scope - the closed scope
1168
+ * @param parent - the enclosing scope
1169
+ * @param container - the cluster's container node
1170
+ */
1171
+ private closeCluster(scope: Scope, parent: Scope, container: number): void {
1172
+ const own = this.ownAttributes.get(container) ?? new Set<string>();
1173
+ this.ownAttributes.set(container, own);
1174
+ for (const attribute of scope.attributes.values()) {
1175
+ if (attribute.name !== CLUSTER_ATTRIBUTE) {
1176
+ own.add(attribute.name);
1177
+ this.setNodeAttribute(container, attribute.name, attribute.value, attribute.line);
1178
+ }
1179
+ }
1180
+ for (const nested of scope.containers) {
1181
+ if (nested !== container && !this.parentOf.has(nested)) {
1182
+ this.setParent(nested, container);
1183
+ }
1184
+ }
1185
+ for (const member of scope.members) {
1186
+ if (member !== container) {
1187
+ this.adoptMember(member, container, scope.line);
1188
+ }
1189
+ }
1190
+ parent.containers.push(container);
1191
+ }
1192
+
1193
+ /**
1194
+ * Put a cluster's member in it, unless it is already in another cluster this one is not inside.
1195
+ * @param member - the member node
1196
+ * @param container - the cluster's container node
1197
+ * @param line - the cluster's line
1198
+ */
1199
+ private adoptMember(member: number, container: number, line: number): void {
1200
+ const existing = this.parentOf.get(member);
1201
+ if (existing === undefined) {
1202
+ this.setParent(member, container);
1203
+ } else if (existing !== container && !this.isAncestor(container, existing)) {
1204
+ this.clusterConflict(member, existing, container, line);
1205
+ }
1206
+ }
1207
+
1208
+ /**
1209
+ * Finish a subgraph that is not a cluster: report its attributes dropped, and hand its nested
1210
+ * containers to the enclosing scope.
1211
+ * @param scope - the closed scope
1212
+ * @param parent - the enclosing scope
1213
+ */
1214
+ private closePlainSubgraph(scope: Scope, parent: Scope): void {
1215
+ if (scope.attributes.size > 0) {
1216
+ const names = [...scope.attributes.keys()].join(", ");
1217
+ this.report.warning(
1218
+ "unsupported",
1219
+ DOT_ISSUE.SUBGRAPH_ATTRIBUTES_DROPPED,
1220
+ `subgraph ${scope.name === null ? "(anonymous)" : JSON.stringify(scope.name)} is not a cluster; its attributes (${names}) cannot be represented and were dropped`,
1221
+ { line: scope.line, element: scope.name },
1222
+ );
1223
+ }
1224
+ for (const nested of scope.containers) {
1225
+ parent.containers.push(nested);
1226
+ }
1227
+ }
1228
+
1229
+ /**
1230
+ * Give every cluster the drawing attributes it inherits and does not set itself (Graphviz's subgraph attribute
1231
+ * inheritance), once the whole graph is read: a cluster reopened later can still set its own.
1232
+ */
1233
+ private applyInherited(): void {
1234
+ for (const [container, attributes] of this.inherited) {
1235
+ const own = this.ownAttributes.get(container);
1236
+ for (const attribute of attributes.values()) {
1237
+ if (own?.has(attribute.name) !== true) {
1238
+ this.setNodeAttribute(container, attribute.name, attribute.value, attribute.line);
1239
+ }
1240
+ }
1241
+ }
1242
+ }
1243
+
1163
1244
  /**
1164
1245
  * Whether `candidate` is an ancestor of `node` through the parents assigned so far.
1165
1246
  * @param candidate - the possible ancestor
@@ -1244,6 +1325,7 @@ class DotParser {
1244
1325
  if (!this.containers.has(index)) {
1245
1326
  this.containers.add(index);
1246
1327
  this.sink.setNodeValue(this.clusterColumn(), index, true);
1328
+ this.inherited.set(index, new Map(scope.graphDefaults));
1247
1329
  }
1248
1330
  scope.container = index;
1249
1331
  } catch (err) {
@@ -1261,6 +1343,9 @@ class DotParser {
1261
1343
  * @param attribute - the attribute
1262
1344
  */
1263
1345
  private scopeAttribute(scope: Scope, attribute: DotAttribute): void {
1346
+ if (INHERITED_GRAPH_ATTRIBUTES.has(attribute.name)) {
1347
+ scope.graphDefaults.set(attribute.name, attribute);
1348
+ }
1264
1349
  if (scope.root) {
1265
1350
  this.setGraphAttribute(attribute);
1266
1351
  return;
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Where Graphviz puts an edge's labels: a stored `lp` (the label's center), and the head and tail labels at
3
+ * `head_lp` / `tail_lp` -- kept only with the edge's stored `pos` (`neato -n2` routes an edge without one again, and
4
+ * places its labels again) -- or where Graphviz's `place_portlabel` (lib/common/splines.c) puts them, when the edge's
5
+ * `labelangle` or `labeldistance` is not its default: `10 * labeldistance` points from the end of the line, turned
6
+ * `labelangle` degrees (default -25) from the line. With both at their defaults Graphviz places end labels as external
7
+ * labels, which graphty leaves to its own place beside the end. Read as offsets from where graphty puts each label:
8
+ * the edge label from the middle of its route, an end label from where the line meets its node.
9
+ */
10
+
11
+ import type { GraphSnapshot } from "@graphty/graph-format";
12
+
13
+ import { type BendPoint, flattenCubic } from "../../styles/canon/bends.js";
14
+ import { num6 } from "../../styles/canon/number.js";
15
+ import type { StyleValue } from "../../styles/types.js";
16
+
17
+ /** Graphviz's `PORT_LABEL_DISTANCE`, in points. */
18
+ const PORT_LABEL_DISTANCE = 10;
19
+
20
+ /** Graphviz's `PORT_LABEL_ANGLE`, in degrees. */
21
+ const PORT_LABEL_ANGLE = -25;
22
+
23
+ /** Graphviz's default node size, in inches. */
24
+ const DEFAULT_SIZE = { w: 0.75, h: 0.5 } as const;
25
+
26
+ /** One attribute of an element as text, or null when it is unset. */
27
+ type Attr = (name: string) => string | null;
28
+
29
+ /** Receives one property's value. */
30
+ type Put = (property: string, value: StyleValue | null) => void;
31
+
32
+ /** What the label places of one graph's edges are read against. */
33
+ export interface LabelPlaceContext {
34
+ /** A node's center from its position, in points, y up. */
35
+ readonly center: (n: number) => BendPoint | null;
36
+ /** A node's attribute. */
37
+ readonly node: (n: number, name: string) => string | null;
38
+ }
39
+
40
+ /**
41
+ * Reads an edge's stored label places and its head and tail label places as offsets.
42
+ * @param snapshot - the graph
43
+ * @param cx - the graph's label place context
44
+ * @param e - the edge
45
+ * @param get - the edge's attributes
46
+ * @param put - receives the values
47
+ */
48
+ export function readLabelPlaces(snapshot: GraphSnapshot, cx: LabelPlaceContext, e: number, get: Attr, put: Put): void {
49
+ const s = snapshot.edgeSource(e);
50
+ const t = snapshot.edgeTarget(e);
51
+ const [source, target] = [cx.center(s), cx.center(t)];
52
+ if (source === null || target === null || s === t) {
53
+ return;
54
+ }
55
+ const route = edgeRoute(source, target, get("pos"));
56
+ const lp = route.start === null ? null : point(get("lp"));
57
+ if (lp !== null && get("label") !== null) {
58
+ const mid = routeMiddle(route.points);
59
+ put("labelOffsetX", num6(lp[0] - mid[0]));
60
+ put("labelOffsetY", num6(mid[1] - lp[1]));
61
+ }
62
+ readEndLabel(cx, route, { node: t, at: target, other: source }, "head", get, put);
63
+ readEndLabel(cx, route, { node: s, at: source, other: target }, "tail", get, put);
64
+ }
65
+
66
+ /** One end of an edge: its node, that node's center and the other end's center. */
67
+ interface EdgeEnd {
68
+ readonly node: number;
69
+ readonly at: BendPoint;
70
+ readonly other: BendPoint;
71
+ }
72
+
73
+ /**
74
+ * Reads one end's label place as an offset from where its line meets its node.
75
+ * @param cx - the graph's label place context
76
+ * @param route - the edge's route
77
+ * @param end - the end's node and the two centers
78
+ * @param which - which end
79
+ * @param get - the edge's attributes
80
+ * @param put - receives the values
81
+ */
82
+ function readEndLabel(
83
+ cx: LabelPlaceContext,
84
+ route: EdgeRoute,
85
+ end: EdgeEnd,
86
+ which: "head" | "tail",
87
+ get: Attr,
88
+ put: Put,
89
+ ): void {
90
+ if (get(`${which}label`) === null) {
91
+ return;
92
+ }
93
+ const head = which === "head";
94
+ const tip = (head ? route.end : route.start) ?? boundary(cx, end.node, end.at, end.other);
95
+ // the nearest route point back from the end that is not the end itself (a spline with no arrow ends at it);
96
+ // the route's last point is the node's center, past the end
97
+ const back = head ? route.points.slice(0, -1).reverse() : route.points.slice(1);
98
+ const toward = back.find((p) => Math.hypot(p[0] - tip[0], p[1] - tip[1]) > 1e-6) ?? end.other;
99
+ const stored = route.start === null ? null : point(get(`${which}_lp`));
100
+ const at = stored ?? portLabel(get, tip, toward);
101
+ if (at !== null) {
102
+ const prefix = head ? "target" : "source";
103
+ put(`${prefix}LabelOffset`, 0);
104
+ put(`${prefix}LabelOffsetX`, num6(at[0] - tip[0]));
105
+ put(`${prefix}LabelOffsetY`, num6(tip[1] - at[1]));
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Where Graphviz's `place_portlabel` puts an end label's center: only when the edge's `labelangle` or
111
+ * `labeldistance` is not its default.
112
+ * @param get - the edge's attributes
113
+ * @param tip - the end of the line
114
+ * @param toward - a point back along the line from the end
115
+ * @returns the center, or null when Graphviz places the label as an external label
116
+ */
117
+ function portLabel(get: Attr, tip: BendPoint, toward: BendPoint): BendPoint | null {
118
+ const turn = finite(get("labelangle"), PORT_LABEL_ANGLE, -180);
119
+ const distance = finite(get("labeldistance"), 1, 0);
120
+ if (turn === PORT_LABEL_ANGLE && distance === 1) {
121
+ return null;
122
+ }
123
+ const angle = Math.atan2(toward[1] - tip[1], toward[0] - tip[0]) + (turn * Math.PI) / 180;
124
+ const dist = PORT_LABEL_DISTANCE * distance;
125
+ return [tip[0] + dist * Math.cos(angle), tip[1] + dist * Math.sin(angle)];
126
+ }
127
+
128
+ /**
129
+ * A number attribute as Graphviz's `late_double` reads it: the default when unset or not a number, at least `low`.
130
+ * @param raw - the value
131
+ * @param fallback - the default
132
+ * @param low - the least value
133
+ * @returns the number
134
+ */
135
+ function finite(raw: string | null, fallback: number, low: number): number {
136
+ const v = raw === null || raw.trim() === "" ? Number.NaN : Number(raw);
137
+ return Number.isFinite(v) ? Math.max(low, v) : fallback;
138
+ }
139
+
140
+ /**
141
+ * An "x,y" point (a trailing `!` allowed).
142
+ * @param raw - the text
143
+ * @returns the point, or null
144
+ */
145
+ function point(raw: string | null): BendPoint | null {
146
+ const parts = (raw ?? "").replace(/!$/, "").split(",").map(Number);
147
+ return parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1]) ? [parts[0], parts[1]] : null;
148
+ }
149
+
150
+ /** An edge's route: its points from center to center, and the ends of its line when stored. */
151
+ interface EdgeRoute {
152
+ readonly points: BendPoint[];
153
+ readonly start: BendPoint | null;
154
+ readonly end: BendPoint | null;
155
+ }
156
+
157
+ /**
158
+ * The route an edge is drawn along: its stored spline's points (flattened) between the two centers, and the ends of
159
+ * its line where `pos` gives arrow points (`s,` / `e,`) or its spline's own ends.
160
+ * @param source - the source's center
161
+ * @param target - the target's center
162
+ * @param pos - the edge's `pos`
163
+ * @returns the route
164
+ */
165
+ function edgeRoute(source: BendPoint, target: BendPoint, pos: string | null): EdgeRoute {
166
+ const tokens = (pos ?? "").split(";")[0].trim().split(/\s+/).filter(Boolean);
167
+ const marked = (flag: string): BendPoint | null => {
168
+ const token = tokens.find((x) => x.startsWith(`${flag},`));
169
+ return token === undefined ? null : point(token.slice(2));
170
+ };
171
+ const controls = tokens.filter((x) => !/^[es],/.test(x)).map((x) => point(x));
172
+ const flat = controls.every((p) => p !== null) && controls.length >= 4 ? flattenCubic(controls) : null;
173
+ if (flat === null) {
174
+ return { points: [source, target], start: null, end: null };
175
+ }
176
+ return {
177
+ points: [source, ...flat, target],
178
+ start: marked("s") ?? flat[0],
179
+ end: marked("e") ?? flat.at(-1) ?? null,
180
+ };
181
+ }
182
+
183
+ /**
184
+ * The point halfway along a route.
185
+ * @param points - the route
186
+ * @returns the point
187
+ */
188
+ function routeMiddle(points: readonly BendPoint[]): BendPoint {
189
+ // ponytail: halfway by length; graphty puts a bent edge's label at its middle segment, close to it
190
+ const lengths = points.slice(1).map((p, i) => Math.hypot(p[0] - points[i][0], p[1] - points[i][1]));
191
+ let left = lengths.reduce((a, b) => a + b, 0) / 2;
192
+ for (let i = 0; i < lengths.length; i++) {
193
+ if (left <= lengths[i] && lengths[i] > 0) {
194
+ const f = left / lengths[i];
195
+ return [
196
+ points[i][0] + f * (points[i + 1][0] - points[i][0]),
197
+ points[i][1] + f * (points[i + 1][1] - points[i][1]),
198
+ ];
199
+ }
200
+ left -= lengths[i];
201
+ }
202
+ return points[0];
203
+ }
204
+
205
+ /**
206
+ * Where the straight line from a node's center toward a point leaves the node, the node taken as the ellipse of its
207
+ * `width` and `height`.
208
+ * @param cx - the label place context
209
+ * @param n - the node
210
+ * @param center - its center
211
+ * @param toward - the point
212
+ * @returns the point on its outline
213
+ */
214
+ function boundary(cx: LabelPlaceContext, n: number, center: BendPoint, toward: BendPoint): BendPoint {
215
+ // ponytail: every shape taken as its ellipse; exact for the circles and ellipses the end labels sit on
216
+ const inch = (name: "width" | "height", fallback: number): number => {
217
+ const v = Number(cx.node(n, name) ?? Number.NaN);
218
+ return (Number.isFinite(v) && v >= 0 ? v : fallback) * 72;
219
+ };
220
+ const [rx, ry] = [inch("width", DEFAULT_SIZE.w) / 2, inch("height", DEFAULT_SIZE.h) / 2];
221
+ const [dx, dy] = [toward[0] - center[0], toward[1] - center[1]];
222
+ const len = Math.hypot(dx, dy);
223
+ if (len === 0 || rx === 0 || ry === 0) {
224
+ return center;
225
+ }
226
+ const r = 1 / Math.hypot(dx / len / rx, dy / len / ry);
227
+ return [center[0] + (dx / len) * r, center[1] + (dy / len) * r];
228
+ }