@graphty/graph-io 0.3.43 → 0.3.45

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 (674) hide show
  1. package/dist/chunks/approximations-DJMHdDvv.js +40 -0
  2. package/dist/chunks/approximations-DJMHdDvv.js.map +1 -0
  3. package/dist/chunks/block-CPCHkX42.js +2777 -0
  4. package/dist/chunks/block-CPCHkX42.js.map +1 -0
  5. package/dist/chunks/{choose-DvpbdRuz.js → choose--jM0yYCo.js} +3 -2
  6. package/dist/chunks/{choose-DvpbdRuz.js.map → choose--jM0yYCo.js.map} +1 -1
  7. package/dist/chunks/{constants-fT3E8JYY.js → constants-BKwqelYD.js} +6 -2
  8. package/dist/chunks/constants-BKwqelYD.js.map +1 -0
  9. package/dist/chunks/convert-BcQ8_jMo.js +59 -0
  10. package/dist/chunks/convert-BcQ8_jMo.js.map +1 -0
  11. package/dist/chunks/emit-DZy6JgdA.js +3456 -0
  12. package/dist/chunks/emit-DZy6JgdA.js.map +1 -0
  13. package/dist/chunks/{escape-B62ZGM_a.js → escape-CgzxiYPg.js} +44 -21
  14. package/dist/chunks/escape-CgzxiYPg.js.map +1 -0
  15. package/dist/chunks/{export-rKLeGQMo.js → export-BvqAXCKh.js} +196 -792
  16. package/dist/chunks/export-BvqAXCKh.js.map +1 -0
  17. package/dist/chunks/{exporter-yLxKBvLE.js → exporter--Mk9gXCJ.js} +4 -3
  18. package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter--Mk9gXCJ.js.map} +1 -1
  19. package/dist/chunks/{exporter-RVtXVetw.js → exporter-C-9cgZKa.js} +1805 -287
  20. package/dist/chunks/exporter-C-9cgZKa.js.map +1 -0
  21. package/dist/chunks/{exporter-8hLNemFk.js → exporter-DFqJhBnj.js} +133 -74
  22. package/dist/chunks/exporter-DFqJhBnj.js.map +1 -0
  23. package/dist/chunks/{exporter-BWwEuOPT.js → exporter-DteVeJki.js} +22 -12
  24. package/dist/chunks/exporter-DteVeJki.js.map +1 -0
  25. package/dist/chunks/format-BpQBx8MZ.js +676 -0
  26. package/dist/chunks/format-BpQBx8MZ.js.map +1 -0
  27. package/dist/chunks/generic-BGO71QBv.js +1347 -0
  28. package/dist/chunks/generic-BGO71QBv.js.map +1 -0
  29. package/dist/chunks/{importer-C98dpSH4.js → importer-B-9Rc1zO.js} +141 -82
  30. package/dist/chunks/importer-B-9Rc1zO.js.map +1 -0
  31. package/dist/chunks/{importer-D794XUTe.js → importer-BVVR740x.js} +31 -8
  32. package/dist/chunks/importer-BVVR740x.js.map +1 -0
  33. package/dist/chunks/{importer-WrGRZb0N.js → importer-C0AjA3Ax.js} +449 -102
  34. package/dist/chunks/importer-C0AjA3Ax.js.map +1 -0
  35. package/dist/chunks/{importer-BbNb7eNg.js → importer-C7pvJe1L.js} +1398 -129
  36. package/dist/chunks/importer-C7pvJe1L.js.map +1 -0
  37. package/dist/chunks/{importer-xZ-3suY1.js → importer-ClwoVx3O.js} +791 -135
  38. package/dist/chunks/importer-ClwoVx3O.js.map +1 -0
  39. package/dist/chunks/{importer-Ht7LNg8L.js → importer-D0sC_6bO.js} +116 -296
  40. package/dist/chunks/importer-D0sC_6bO.js.map +1 -0
  41. package/dist/chunks/{importer-Dz7tI8Sa.js → importer-EHQk1jbM.js} +617 -115
  42. package/dist/chunks/importer-EHQk1jbM.js.map +1 -0
  43. package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-DJZRZ6jd.js} +123 -32
  44. package/dist/chunks/json-elements-DJZRZ6jd.js.map +1 -0
  45. package/dist/chunks/lexicon-WMsNddyU.js +509 -0
  46. package/dist/chunks/lexicon-WMsNddyU.js.map +1 -0
  47. package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-G4MqRdux.js} +3 -2
  48. package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-G4MqRdux.js.map} +1 -1
  49. package/dist/chunks/{records-Cu4bxYOm.js → records-CiaWZrFH.js} +2 -2
  50. package/dist/chunks/{records-Cu4bxYOm.js.map → records-CiaWZrFH.js.map} +1 -1
  51. package/dist/chunks/styles-DvoFBKCK.js +690 -0
  52. package/dist/chunks/styles-DvoFBKCK.js.map +1 -0
  53. package/dist/chunks/styles-yed-Cz9rLBCP.js +842 -0
  54. package/dist/chunks/styles-yed-Cz9rLBCP.js.map +1 -0
  55. package/dist/chunks/styles-zNTmz5R7.js +2102 -0
  56. package/dist/chunks/styles-zNTmz5R7.js.map +1 -0
  57. package/dist/chunks/{text-DHOJXnED.js → text-CzJNFOS9.js} +2 -2
  58. package/dist/chunks/{text-DHOJXnED.js.map → text-CzJNFOS9.js.map} +1 -1
  59. package/dist/chunks/units-XMZFIFe1.js +19 -0
  60. package/dist/chunks/units-XMZFIFe1.js.map +1 -0
  61. package/dist/chunks/writer-gQ8kx99H.js +448 -0
  62. package/dist/chunks/writer-gQ8kx99H.js.map +1 -0
  63. package/dist/csv.js +5 -4
  64. package/dist/csv.js.map +1 -1
  65. package/dist/cx.js +1 -1
  66. package/dist/cx2.js +2 -2
  67. package/dist/cys.js +1 -1
  68. package/dist/dot.js +5 -2
  69. package/dist/dot.js.map +1 -1
  70. package/dist/gexf.js +292 -412
  71. package/dist/gexf.js.map +1 -1
  72. package/dist/gml.js +927 -74
  73. package/dist/gml.js.map +1 -1
  74. package/dist/graph-io.js +351 -236
  75. package/dist/graph-io.js.map +1 -1
  76. package/dist/graphml.js +4 -2
  77. package/dist/graphml.js.map +1 -1
  78. package/dist/json.js +1 -1
  79. package/dist/neo4j.js +4 -3
  80. package/dist/neo4j.js.map +1 -1
  81. package/dist/obo.js +1 -1
  82. package/dist/pajek.js +4 -2
  83. package/dist/positions.d.ts +1 -0
  84. package/dist/positions.js +427 -0
  85. package/dist/positions.js.map +1 -0
  86. package/dist/src/common/codes.d.ts +6 -0
  87. package/dist/src/common/codes.d.ts.map +1 -1
  88. package/dist/src/common/codes.js +6 -0
  89. package/dist/src/common/codes.js.map +1 -1
  90. package/dist/src/common/escape.d.ts.map +1 -1
  91. package/dist/src/common/escape.js +4 -2
  92. package/dist/src/common/escape.js.map +1 -1
  93. package/dist/src/common/export.d.ts +10 -0
  94. package/dist/src/common/export.d.ts.map +1 -1
  95. package/dist/src/common/export.js +123 -100
  96. package/dist/src/common/export.js.map +1 -1
  97. package/dist/src/common/input.d.ts.map +1 -1
  98. package/dist/src/common/input.js +8 -1
  99. package/dist/src/common/input.js.map +1 -1
  100. package/dist/src/common/json-elements.d.ts +12 -9
  101. package/dist/src/common/json-elements.d.ts.map +1 -1
  102. package/dist/src/common/json-elements.js +160 -37
  103. package/dist/src/common/json-elements.js.map +1 -1
  104. package/dist/src/common/notes.d.ts +42 -0
  105. package/dist/src/common/notes.d.ts.map +1 -0
  106. package/dist/src/common/notes.js +72 -0
  107. package/dist/src/common/notes.js.map +1 -0
  108. package/dist/src/common/report.d.ts +18 -0
  109. package/dist/src/common/report.d.ts.map +1 -1
  110. package/dist/src/common/report.js +36 -1
  111. package/dist/src/common/report.js.map +1 -1
  112. package/dist/src/common/units.d.ts +24 -0
  113. package/dist/src/common/units.d.ts.map +1 -0
  114. package/dist/src/common/units.js +26 -0
  115. package/dist/src/common/units.js.map +1 -0
  116. package/dist/src/common/xml.d.ts +18 -0
  117. package/dist/src/common/xml.d.ts.map +1 -1
  118. package/dist/src/common/xml.js +42 -5
  119. package/dist/src/common/xml.js.map +1 -1
  120. package/dist/src/formats/cx/exporter.d.ts +6 -0
  121. package/dist/src/formats/cx/exporter.d.ts.map +1 -1
  122. package/dist/src/formats/cx/exporter.js +71 -8
  123. package/dist/src/formats/cx/exporter.js.map +1 -1
  124. package/dist/src/formats/cx/importer.d.ts +5 -2
  125. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cx/importer.js +102 -72
  127. package/dist/src/formats/cx/importer.js.map +1 -1
  128. package/dist/src/formats/cx/styles.d.ts +102 -0
  129. package/dist/src/formats/cx/styles.d.ts.map +1 -0
  130. package/dist/src/formats/cx/styles.js +225 -0
  131. package/dist/src/formats/cx/styles.js.map +1 -0
  132. package/dist/src/formats/cx2/exporter.d.ts +5 -0
  133. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  134. package/dist/src/formats/cx2/exporter.js +181 -71
  135. package/dist/src/formats/cx2/exporter.js.map +1 -1
  136. package/dist/src/formats/cx2/importer.d.ts +4 -1
  137. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  138. package/dist/src/formats/cx2/importer.js +19 -1
  139. package/dist/src/formats/cx2/importer.js.map +1 -1
  140. package/dist/src/formats/cx2/styles.d.ts +18 -0
  141. package/dist/src/formats/cx2/styles.d.ts.map +1 -0
  142. package/dist/src/formats/cx2/styles.js +24 -0
  143. package/dist/src/formats/cx2/styles.js.map +1 -0
  144. package/dist/src/formats/cys/constants.d.ts +2 -0
  145. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  146. package/dist/src/formats/cys/constants.js +2 -0
  147. package/dist/src/formats/cys/constants.js.map +1 -1
  148. package/dist/src/formats/cys/exporter.d.ts +6 -2
  149. package/dist/src/formats/cys/exporter.d.ts.map +1 -1
  150. package/dist/src/formats/cys/exporter.js +215 -53
  151. package/dist/src/formats/cys/exporter.js.map +1 -1
  152. package/dist/src/formats/cys/importer.d.ts +2 -1
  153. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  154. package/dist/src/formats/cys/importer.js +119 -6
  155. package/dist/src/formats/cys/importer.js.map +1 -1
  156. package/dist/src/formats/cys/session.d.ts +2 -0
  157. package/dist/src/formats/cys/session.d.ts.map +1 -1
  158. package/dist/src/formats/cys/session.js +5 -0
  159. package/dist/src/formats/cys/session.js.map +1 -1
  160. package/dist/src/formats/cys/styles.d.ts +38 -0
  161. package/dist/src/formats/cys/styles.d.ts.map +1 -0
  162. package/dist/src/formats/cys/styles.js +213 -0
  163. package/dist/src/formats/cys/styles.js.map +1 -0
  164. package/dist/src/formats/cys/tables.d.ts +8 -3
  165. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  166. package/dist/src/formats/cys/tables.js +88 -34
  167. package/dist/src/formats/cys/tables.js.map +1 -1
  168. package/dist/src/formats/dot/exporter.d.ts +2 -0
  169. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  170. package/dist/src/formats/dot/exporter.js +195 -81
  171. package/dist/src/formats/dot/exporter.js.map +1 -1
  172. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  173. package/dist/src/formats/dot/importer.js +100 -20
  174. package/dist/src/formats/dot/importer.js.map +1 -1
  175. package/dist/src/formats/dot/index.d.ts +1 -0
  176. package/dist/src/formats/dot/index.d.ts.map +1 -1
  177. package/dist/src/formats/dot/index.js +1 -0
  178. package/dist/src/formats/dot/index.js.map +1 -1
  179. package/dist/src/formats/dot/positions.d.ts +14 -0
  180. package/dist/src/formats/dot/positions.d.ts.map +1 -0
  181. package/dist/src/formats/dot/positions.js +70 -0
  182. package/dist/src/formats/dot/positions.js.map +1 -0
  183. package/dist/src/formats/dot/styles.d.ts +82 -0
  184. package/dist/src/formats/dot/styles.d.ts.map +1 -0
  185. package/dist/src/formats/dot/styles.js +1496 -0
  186. package/dist/src/formats/dot/styles.js.map +1 -0
  187. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  188. package/dist/src/formats/gexf/exporter.js +20 -5
  189. package/dist/src/formats/gexf/exporter.js.map +1 -1
  190. package/dist/src/formats/gexf/importer.d.ts +8 -1
  191. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  192. package/dist/src/formats/gexf/importer.js +251 -131
  193. package/dist/src/formats/gexf/importer.js.map +1 -1
  194. package/dist/src/formats/gexf/index.d.ts +8 -0
  195. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  196. package/dist/src/formats/gexf/index.js +10 -2
  197. package/dist/src/formats/gexf/index.js.map +1 -1
  198. package/dist/src/formats/gexf/schema.d.ts +5 -0
  199. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  200. package/dist/src/formats/gexf/schema.js +5 -0
  201. package/dist/src/formats/gexf/schema.js.map +1 -1
  202. package/dist/src/formats/gexf/styles.d.ts +74 -0
  203. package/dist/src/formats/gexf/styles.d.ts.map +1 -0
  204. package/dist/src/formats/gexf/styles.js +604 -0
  205. package/dist/src/formats/gexf/styles.js.map +1 -0
  206. package/dist/src/formats/gml/exporter.d.ts +1 -5
  207. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  208. package/dist/src/formats/gml/exporter.js +19 -8
  209. package/dist/src/formats/gml/exporter.js.map +1 -1
  210. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  211. package/dist/src/formats/gml/importer.js +4 -0
  212. package/dist/src/formats/gml/importer.js.map +1 -1
  213. package/dist/src/formats/gml/index.d.ts +2 -1
  214. package/dist/src/formats/gml/index.d.ts.map +1 -1
  215. package/dist/src/formats/gml/index.js +2 -1
  216. package/dist/src/formats/gml/index.js.map +1 -1
  217. package/dist/src/formats/gml/positions.d.ts +14 -0
  218. package/dist/src/formats/gml/positions.d.ts.map +1 -0
  219. package/dist/src/formats/gml/positions.js +46 -0
  220. package/dist/src/formats/gml/positions.js.map +1 -0
  221. package/dist/src/formats/gml/styles.d.ts +59 -0
  222. package/dist/src/formats/gml/styles.d.ts.map +1 -0
  223. package/dist/src/formats/gml/styles.js +1056 -0
  224. package/dist/src/formats/gml/styles.js.map +1 -0
  225. package/dist/src/formats/gml/syntax.d.ts +11 -0
  226. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  227. package/dist/src/formats/gml/syntax.js +151 -62
  228. package/dist/src/formats/gml/syntax.js.map +1 -1
  229. package/dist/src/formats/graphml/constants.d.ts +4 -0
  230. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  231. package/dist/src/formats/graphml/constants.js +5 -1
  232. package/dist/src/formats/graphml/constants.js.map +1 -1
  233. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  234. package/dist/src/formats/graphml/exporter.js +133 -65
  235. package/dist/src/formats/graphml/exporter.js.map +1 -1
  236. package/dist/src/formats/graphml/importer.d.ts +4 -1
  237. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  238. package/dist/src/formats/graphml/importer.js +100 -44
  239. package/dist/src/formats/graphml/importer.js.map +1 -1
  240. package/dist/src/formats/graphml/index.d.ts +1 -0
  241. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  242. package/dist/src/formats/graphml/index.js +1 -0
  243. package/dist/src/formats/graphml/index.js.map +1 -1
  244. package/dist/src/formats/graphml/styles-plain.d.ts +19 -0
  245. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -0
  246. package/dist/src/formats/graphml/styles-plain.js +187 -0
  247. package/dist/src/formats/graphml/styles-plain.js.map +1 -0
  248. package/dist/src/formats/graphml/styles-yed.d.ts +179 -0
  249. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -0
  250. package/dist/src/formats/graphml/styles-yed.js +1086 -0
  251. package/dist/src/formats/graphml/styles-yed.js.map +1 -0
  252. package/dist/src/formats/graphml/styles-yfiles3.d.ts +19 -0
  253. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -0
  254. package/dist/src/formats/graphml/styles-yfiles3.js +508 -0
  255. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -0
  256. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  257. package/dist/src/formats/graphml/tree.js +34 -19
  258. package/dist/src/formats/graphml/tree.js.map +1 -1
  259. package/dist/src/formats/graphml/yfiles.d.ts +16 -2
  260. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  261. package/dist/src/formats/graphml/yfiles.js +83 -12
  262. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  263. package/dist/src/formats/json/exporter.d.ts +5 -0
  264. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  265. package/dist/src/formats/json/exporter.js +68 -25
  266. package/dist/src/formats/json/exporter.js.map +1 -1
  267. package/dist/src/formats/json/importer.d.ts +22 -3
  268. package/dist/src/formats/json/importer.d.ts.map +1 -1
  269. package/dist/src/formats/json/importer.js +439 -264
  270. package/dist/src/formats/json/importer.js.map +1 -1
  271. package/dist/src/formats/json/positions.d.ts +16 -0
  272. package/dist/src/formats/json/positions.d.ts.map +1 -0
  273. package/dist/src/formats/json/positions.js +44 -0
  274. package/dist/src/formats/json/positions.js.map +1 -0
  275. package/dist/src/formats/json/styles.d.ts +102 -0
  276. package/dist/src/formats/json/styles.d.ts.map +1 -0
  277. package/dist/src/formats/json/styles.js +1753 -0
  278. package/dist/src/formats/json/styles.js.map +1 -0
  279. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  280. package/dist/src/formats/neo4j/exporter.js +2 -1
  281. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  282. package/dist/src/formats/pajek/exporter.d.ts +2 -0
  283. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/pajek/exporter.js +142 -76
  285. package/dist/src/formats/pajek/exporter.js.map +1 -1
  286. package/dist/src/formats/pajek/importer.d.ts +4 -0
  287. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  288. package/dist/src/formats/pajek/importer.js +60 -6
  289. package/dist/src/formats/pajek/importer.js.map +1 -1
  290. package/dist/src/formats/pajek/index.d.ts +2 -0
  291. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  292. package/dist/src/formats/pajek/index.js +2 -0
  293. package/dist/src/formats/pajek/index.js.map +1 -1
  294. package/dist/src/formats/pajek/styles.d.ts +50 -0
  295. package/dist/src/formats/pajek/styles.d.ts.map +1 -0
  296. package/dist/src/formats/pajek/styles.js +569 -0
  297. package/dist/src/formats/pajek/styles.js.map +1 -0
  298. package/dist/src/formats/pajek/syntax.d.ts +6 -0
  299. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  300. package/dist/src/formats/pajek/syntax.js +6 -0
  301. package/dist/src/formats/pajek/syntax.js.map +1 -1
  302. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  303. package/dist/src/formats/xgmml/columns.js +34 -9
  304. package/dist/src/formats/xgmml/columns.js.map +1 -1
  305. package/dist/src/formats/xgmml/constants.d.ts +2 -0
  306. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  307. package/dist/src/formats/xgmml/constants.js +3 -1
  308. package/dist/src/formats/xgmml/constants.js.map +1 -1
  309. package/dist/src/formats/xgmml/document.d.ts +12 -8
  310. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  311. package/dist/src/formats/xgmml/document.js +56 -13
  312. package/dist/src/formats/xgmml/document.js.map +1 -1
  313. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  314. package/dist/src/formats/xgmml/emit.js +12 -6
  315. package/dist/src/formats/xgmml/emit.js.map +1 -1
  316. package/dist/src/formats/xgmml/exporter.d.ts +3 -1
  317. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  318. package/dist/src/formats/xgmml/exporter.js +22 -9
  319. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  320. package/dist/src/formats/xgmml/importer.d.ts +2 -1
  321. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  322. package/dist/src/formats/xgmml/importer.js +31 -24
  323. package/dist/src/formats/xgmml/importer.js.map +1 -1
  324. package/dist/src/formats/xgmml/styles.d.ts +104 -0
  325. package/dist/src/formats/xgmml/styles.d.ts.map +1 -0
  326. package/dist/src/formats/xgmml/styles.js +310 -0
  327. package/dist/src/formats/xgmml/styles.js.map +1 -0
  328. package/dist/src/index.d.ts +9 -7
  329. package/dist/src/index.d.ts.map +1 -1
  330. package/dist/src/index.js +7 -7
  331. package/dist/src/index.js.map +1 -1
  332. package/dist/src/positions/codes.d.ts +31 -0
  333. package/dist/src/positions/codes.d.ts.map +1 -0
  334. package/dist/src/positions/codes.js +26 -0
  335. package/dist/src/positions/codes.js.map +1 -0
  336. package/dist/src/positions/convert.d.ts +58 -0
  337. package/dist/src/positions/convert.d.ts.map +1 -0
  338. package/dist/src/positions/convert.js +107 -0
  339. package/dist/src/positions/convert.js.map +1 -0
  340. package/dist/src/positions/extract.d.ts +27 -0
  341. package/dist/src/positions/extract.d.ts.map +1 -0
  342. package/dist/src/positions/extract.js +526 -0
  343. package/dist/src/positions/extract.js.map +1 -0
  344. package/dist/src/positions/index.d.ts +10 -0
  345. package/dist/src/positions/index.d.ts.map +1 -0
  346. package/dist/src/positions/index.js +9 -0
  347. package/dist/src/positions/index.js.map +1 -0
  348. package/dist/src/positions/types.d.ts +208 -0
  349. package/dist/src/positions/types.d.ts.map +1 -0
  350. package/dist/src/positions/types.js +10 -0
  351. package/dist/src/positions/types.js.map +1 -0
  352. package/dist/src/registry.d.ts +30 -0
  353. package/dist/src/registry.d.ts.map +1 -1
  354. package/dist/src/registry.js +130 -9
  355. package/dist/src/registry.js.map +1 -1
  356. package/dist/src/styles/annotations.d.ts +132 -0
  357. package/dist/src/styles/annotations.d.ts.map +1 -0
  358. package/dist/src/styles/annotations.js +320 -0
  359. package/dist/src/styles/annotations.js.map +1 -0
  360. package/dist/src/styles/budget.d.ts +45 -0
  361. package/dist/src/styles/budget.d.ts.map +1 -0
  362. package/dist/src/styles/budget.js +58 -0
  363. package/dist/src/styles/budget.js.map +1 -0
  364. package/dist/src/styles/canon/bends.d.ts +32 -0
  365. package/dist/src/styles/canon/bends.d.ts.map +1 -0
  366. package/dist/src/styles/canon/bends.js +74 -0
  367. package/dist/src/styles/canon/bends.js.map +1 -0
  368. package/dist/src/styles/canon/color-tables.d.ts +22 -0
  369. package/dist/src/styles/canon/color-tables.d.ts.map +1 -0
  370. package/dist/src/styles/canon/color-tables.js +369 -0
  371. package/dist/src/styles/canon/color-tables.js.map +1 -0
  372. package/dist/src/styles/canon/color.d.ts +66 -0
  373. package/dist/src/styles/canon/color.d.ts.map +1 -0
  374. package/dist/src/styles/canon/color.js +548 -0
  375. package/dist/src/styles/canon/color.js.map +1 -0
  376. package/dist/src/styles/canon/enums.d.ts +25 -0
  377. package/dist/src/styles/canon/enums.d.ts.map +1 -0
  378. package/dist/src/styles/canon/enums.js +187 -0
  379. package/dist/src/styles/canon/enums.js.map +1 -0
  380. package/dist/src/styles/canon/graphviz.d.ts +48 -0
  381. package/dist/src/styles/canon/graphviz.d.ts.map +1 -0
  382. package/dist/src/styles/canon/graphviz.js +160 -0
  383. package/dist/src/styles/canon/graphviz.js.map +1 -0
  384. package/dist/src/styles/canon/index.d.ts +13 -0
  385. package/dist/src/styles/canon/index.d.ts.map +1 -0
  386. package/dist/src/styles/canon/index.js +13 -0
  387. package/dist/src/styles/canon/index.js.map +1 -0
  388. package/dist/src/styles/canon/number.d.ts +59 -0
  389. package/dist/src/styles/canon/number.d.ts.map +1 -0
  390. package/dist/src/styles/canon/number.js +142 -0
  391. package/dist/src/styles/canon/number.js.map +1 -0
  392. package/dist/src/styles/canon/site.d.ts +51 -0
  393. package/dist/src/styles/canon/site.d.ts.map +1 -0
  394. package/dist/src/styles/canon/site.js +63 -0
  395. package/dist/src/styles/canon/site.js.map +1 -0
  396. package/dist/src/styles/canon/text.d.ts +61 -0
  397. package/dist/src/styles/canon/text.d.ts.map +1 -0
  398. package/dist/src/styles/canon/text.js +199 -0
  399. package/dist/src/styles/canon/text.js.map +1 -0
  400. package/dist/src/styles/codes.d.ts +95 -0
  401. package/dist/src/styles/codes.d.ts.map +1 -0
  402. package/dist/src/styles/codes.js +97 -0
  403. package/dist/src/styles/codes.js.map +1 -0
  404. package/dist/src/styles/cyjs/cascade.d.ts +134 -0
  405. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -0
  406. package/dist/src/styles/cyjs/cascade.js +2252 -0
  407. package/dist/src/styles/cyjs/cascade.js.map +1 -0
  408. package/dist/src/styles/cyjs/defaults-table.d.ts +25 -0
  409. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -0
  410. package/dist/src/styles/cyjs/defaults-table.js +76 -0
  411. package/dist/src/styles/cyjs/defaults-table.js.map +1 -0
  412. package/dist/src/styles/cyjs/emit.d.ts +82 -0
  413. package/dist/src/styles/cyjs/emit.d.ts.map +1 -0
  414. package/dist/src/styles/cyjs/emit.js +791 -0
  415. package/dist/src/styles/cyjs/emit.js.map +1 -0
  416. package/dist/src/styles/cyjs/index.d.ts +13 -0
  417. package/dist/src/styles/cyjs/index.d.ts.map +1 -0
  418. package/dist/src/styles/cyjs/index.js +13 -0
  419. package/dist/src/styles/cyjs/index.js.map +1 -0
  420. package/dist/src/styles/cyjs/live.d.ts +46 -0
  421. package/dist/src/styles/cyjs/live.d.ts.map +1 -0
  422. package/dist/src/styles/cyjs/live.js +108 -0
  423. package/dist/src/styles/cyjs/live.js.map +1 -0
  424. package/dist/src/styles/cyjs/mappers.d.ts +147 -0
  425. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -0
  426. package/dist/src/styles/cyjs/mappers.js +744 -0
  427. package/dist/src/styles/cyjs/mappers.js.map +1 -0
  428. package/dist/src/styles/cyjs/selector.d.ts +113 -0
  429. package/dist/src/styles/cyjs/selector.d.ts.map +1 -0
  430. package/dist/src/styles/cyjs/selector.js +611 -0
  431. package/dist/src/styles/cyjs/selector.js.map +1 -0
  432. package/dist/src/styles/cyjs/stylesheet-text.d.ts +37 -0
  433. package/dist/src/styles/cyjs/stylesheet-text.d.ts.map +1 -0
  434. package/dist/src/styles/cyjs/stylesheet-text.js +181 -0
  435. package/dist/src/styles/cyjs/stylesheet-text.js.map +1 -0
  436. package/dist/src/styles/cytoscape/emit.d.ts +125 -0
  437. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -0
  438. package/dist/src/styles/cytoscape/emit.js +1025 -0
  439. package/dist/src/styles/cytoscape/emit.js.map +1 -0
  440. package/dist/src/styles/cytoscape/index.d.ts +10 -0
  441. package/dist/src/styles/cytoscape/index.d.ts.map +1 -0
  442. package/dist/src/styles/cytoscape/index.js +10 -0
  443. package/dist/src/styles/cytoscape/index.js.map +1 -0
  444. package/dist/src/styles/cytoscape/lexicon.d.ts +49 -0
  445. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -0
  446. package/dist/src/styles/cytoscape/lexicon.js +605 -0
  447. package/dist/src/styles/cytoscape/lexicon.js.map +1 -0
  448. package/dist/src/styles/cytoscape/mappings.d.ts +171 -0
  449. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -0
  450. package/dist/src/styles/cytoscape/mappings.js +460 -0
  451. package/dist/src/styles/cytoscape/mappings.js.map +1 -0
  452. package/dist/src/styles/cytoscape/resolve.d.ts +137 -0
  453. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -0
  454. package/dist/src/styles/cytoscape/resolve.js +381 -0
  455. package/dist/src/styles/cytoscape/resolve.js.map +1 -0
  456. package/dist/src/styles/cytoscape/translate.d.ts +50 -0
  457. package/dist/src/styles/cytoscape/translate.d.ts.map +1 -0
  458. package/dist/src/styles/cytoscape/translate.js +156 -0
  459. package/dist/src/styles/cytoscape/translate.js.map +1 -0
  460. package/dist/src/styles/defaults.d.ts +90 -0
  461. package/dist/src/styles/defaults.d.ts.map +1 -0
  462. package/dist/src/styles/defaults.js +414 -0
  463. package/dist/src/styles/defaults.js.map +1 -0
  464. package/dist/src/styles/index.d.ts +15 -0
  465. package/dist/src/styles/index.d.ts.map +1 -0
  466. package/dist/src/styles/index.js +14 -0
  467. package/dist/src/styles/index.js.map +1 -0
  468. package/dist/src/styles/internal.d.ts +17 -0
  469. package/dist/src/styles/internal.d.ts.map +1 -0
  470. package/dist/src/styles/internal.js +16 -0
  471. package/dist/src/styles/internal.js.map +1 -0
  472. package/dist/src/styles/io/approximations.d.ts +24 -0
  473. package/dist/src/styles/io/approximations.d.ts.map +1 -0
  474. package/dist/src/styles/io/approximations.js +51 -0
  475. package/dist/src/styles/io/approximations.js.map +1 -0
  476. package/dist/src/styles/io/block.d.ts +166 -0
  477. package/dist/src/styles/io/block.d.ts.map +1 -0
  478. package/dist/src/styles/io/block.js +930 -0
  479. package/dist/src/styles/io/block.js.map +1 -0
  480. package/dist/src/styles/io/generic.d.ts +88 -0
  481. package/dist/src/styles/io/generic.d.ts.map +1 -0
  482. package/dist/src/styles/io/generic.js +516 -0
  483. package/dist/src/styles/io/generic.js.map +1 -0
  484. package/dist/src/styles/io/index.d.ts +8 -0
  485. package/dist/src/styles/io/index.d.ts.map +1 -0
  486. package/dist/src/styles/io/index.js +7 -0
  487. package/dist/src/styles/io/index.js.map +1 -0
  488. package/dist/src/styles/io/writer.d.ts +89 -0
  489. package/dist/src/styles/io/writer.d.ts.map +1 -0
  490. package/dist/src/styles/io/writer.js +626 -0
  491. package/dist/src/styles/io/writer.js.map +1 -0
  492. package/dist/src/styles/notes.d.ts +47 -0
  493. package/dist/src/styles/notes.d.ts.map +1 -0
  494. package/dist/src/styles/notes.js +140 -0
  495. package/dist/src/styles/notes.js.map +1 -0
  496. package/dist/src/styles/plan/classes.d.ts +31 -0
  497. package/dist/src/styles/plan/classes.d.ts.map +1 -0
  498. package/dist/src/styles/plan/classes.js +139 -0
  499. package/dist/src/styles/plan/classes.js.map +1 -0
  500. package/dist/src/styles/plan/continuous.d.ts +32 -0
  501. package/dist/src/styles/plan/continuous.d.ts.map +1 -0
  502. package/dist/src/styles/plan/continuous.js +165 -0
  503. package/dist/src/styles/plan/continuous.js.map +1 -0
  504. package/dist/src/styles/plan/discrete.d.ts +39 -0
  505. package/dist/src/styles/plan/discrete.d.ts.map +1 -0
  506. package/dist/src/styles/plan/discrete.js +127 -0
  507. package/dist/src/styles/plan/discrete.js.map +1 -0
  508. package/dist/src/styles/plan/families.d.ts +31 -0
  509. package/dist/src/styles/plan/families.d.ts.map +1 -0
  510. package/dist/src/styles/plan/families.js +95 -0
  511. package/dist/src/styles/plan/families.js.map +1 -0
  512. package/dist/src/styles/plan/features.d.ts +58 -0
  513. package/dist/src/styles/plan/features.d.ts.map +1 -0
  514. package/dist/src/styles/plan/features.js +185 -0
  515. package/dist/src/styles/plan/features.js.map +1 -0
  516. package/dist/src/styles/plan/index.d.ts +7 -0
  517. package/dist/src/styles/plan/index.d.ts.map +1 -0
  518. package/dist/src/styles/plan/index.js +7 -0
  519. package/dist/src/styles/plan/index.js.map +1 -0
  520. package/dist/src/styles/plan/plan.d.ts +71 -0
  521. package/dist/src/styles/plan/plan.d.ts.map +1 -0
  522. package/dist/src/styles/plan/plan.js +893 -0
  523. package/dist/src/styles/plan/plan.js.map +1 -0
  524. package/dist/src/styles/plan/resolve.d.ts +137 -0
  525. package/dist/src/styles/plan/resolve.d.ts.map +1 -0
  526. package/dist/src/styles/plan/resolve.js +587 -0
  527. package/dist/src/styles/plan/resolve.js.map +1 -0
  528. package/dist/src/styles/types.d.ts +702 -0
  529. package/dist/src/styles/types.d.ts.map +1 -0
  530. package/dist/src/styles/types.js +10 -0
  531. package/dist/src/styles/types.js.map +1 -0
  532. package/dist/src/styles/vocabulary.d.ts +41 -0
  533. package/dist/src/styles/vocabulary.d.ts.map +1 -0
  534. package/dist/src/styles/vocabulary.js +140 -0
  535. package/dist/src/styles/vocabulary.js.map +1 -0
  536. package/dist/src/types.d.ts +64 -1
  537. package/dist/src/types.d.ts.map +1 -1
  538. package/dist/src/types.js.map +1 -1
  539. package/dist/styles.d.ts +1 -0
  540. package/dist/styles.js +322 -0
  541. package/dist/styles.js.map +1 -0
  542. package/dist/xgmml.js +5 -4
  543. package/dist/xgmml.js.map +1 -1
  544. package/package.json +13 -2
  545. package/src/common/codes.ts +7 -0
  546. package/src/common/escape.ts +5 -2
  547. package/src/common/export.ts +179 -140
  548. package/src/common/input.ts +8 -4
  549. package/src/common/json-elements.ts +169 -38
  550. package/src/common/notes.ts +94 -0
  551. package/src/common/report.ts +41 -1
  552. package/src/common/units.ts +42 -0
  553. package/src/common/xml.ts +45 -5
  554. package/src/formats/cx/exporter.ts +95 -11
  555. package/src/formats/cx/importer.ts +126 -90
  556. package/src/formats/cx/styles.ts +304 -0
  557. package/src/formats/cx2/exporter.ts +234 -77
  558. package/src/formats/cx2/importer.ts +19 -1
  559. package/src/formats/cx2/styles.ts +29 -0
  560. package/src/formats/cys/constants.ts +3 -0
  561. package/src/formats/cys/exporter.ts +246 -60
  562. package/src/formats/cys/importer.ts +125 -9
  563. package/src/formats/cys/session.ts +6 -0
  564. package/src/formats/cys/styles.ts +254 -0
  565. package/src/formats/cys/tables.ts +117 -48
  566. package/src/formats/dot/exporter.ts +262 -126
  567. package/src/formats/dot/importer.ts +111 -20
  568. package/src/formats/dot/index.ts +1 -0
  569. package/src/formats/dot/positions.ts +77 -0
  570. package/src/formats/dot/styles.ts +1755 -0
  571. package/src/formats/gexf/exporter.ts +27 -11
  572. package/src/formats/gexf/importer.ts +308 -158
  573. package/src/formats/gexf/index.ts +10 -0
  574. package/src/formats/gexf/schema.ts +5 -0
  575. package/src/formats/gexf/styles.ts +719 -0
  576. package/src/formats/gml/exporter.ts +33 -14
  577. package/src/formats/gml/importer.ts +4 -0
  578. package/src/formats/gml/index.ts +2 -1
  579. package/src/formats/gml/positions.ts +52 -0
  580. package/src/formats/gml/styles.ts +1248 -0
  581. package/src/formats/gml/syntax.ts +173 -62
  582. package/src/formats/graphml/constants.ts +5 -0
  583. package/src/formats/graphml/exporter.ts +163 -71
  584. package/src/formats/graphml/importer.ts +119 -45
  585. package/src/formats/graphml/index.ts +1 -0
  586. package/src/formats/graphml/styles-plain.ts +236 -0
  587. package/src/formats/graphml/styles-yed.ts +1221 -0
  588. package/src/formats/graphml/styles-yfiles3.ts +573 -0
  589. package/src/formats/graphml/tree.ts +36 -20
  590. package/src/formats/graphml/yfiles.ts +89 -13
  591. package/src/formats/json/exporter.ts +76 -26
  592. package/src/formats/json/importer.ts +541 -322
  593. package/src/formats/json/positions.ts +50 -0
  594. package/src/formats/json/styles.ts +2082 -0
  595. package/src/formats/neo4j/exporter.ts +2 -1
  596. package/src/formats/pajek/exporter.ts +195 -106
  597. package/src/formats/pajek/importer.ts +78 -9
  598. package/src/formats/pajek/index.ts +2 -0
  599. package/src/formats/pajek/styles.ts +685 -0
  600. package/src/formats/pajek/syntax.ts +7 -0
  601. package/src/formats/xgmml/columns.ts +39 -9
  602. package/src/formats/xgmml/constants.ts +3 -0
  603. package/src/formats/xgmml/document.ts +54 -12
  604. package/src/formats/xgmml/emit.ts +11 -6
  605. package/src/formats/xgmml/exporter.ts +32 -13
  606. package/src/formats/xgmml/importer.ts +43 -29
  607. package/src/formats/xgmml/styles.ts +400 -0
  608. package/src/index.ts +16 -0
  609. package/src/positions/codes.ts +32 -0
  610. package/src/positions/convert.ts +123 -0
  611. package/src/positions/extract.ts +619 -0
  612. package/src/positions/index.ts +23 -0
  613. package/src/positions/types.ts +221 -0
  614. package/src/registry.ts +179 -8
  615. package/src/styles/annotations.ts +478 -0
  616. package/src/styles/budget.ts +60 -0
  617. package/src/styles/canon/bends.ts +84 -0
  618. package/src/styles/canon/color-tables.ts +386 -0
  619. package/src/styles/canon/color.ts +624 -0
  620. package/src/styles/canon/enums.ts +211 -0
  621. package/src/styles/canon/graphviz.ts +189 -0
  622. package/src/styles/canon/index.ts +13 -0
  623. package/src/styles/canon/number.ts +152 -0
  624. package/src/styles/canon/site.ts +87 -0
  625. package/src/styles/canon/text.ts +221 -0
  626. package/src/styles/codes.ts +104 -0
  627. package/src/styles/cyjs/cascade.ts +2670 -0
  628. package/src/styles/cyjs/defaults-table.ts +82 -0
  629. package/src/styles/cyjs/emit.ts +952 -0
  630. package/src/styles/cyjs/index.ts +37 -0
  631. package/src/styles/cyjs/live.ts +147 -0
  632. package/src/styles/cyjs/mappers.ts +879 -0
  633. package/src/styles/cyjs/selector.ts +778 -0
  634. package/src/styles/cyjs/stylesheet-text.ts +214 -0
  635. package/src/styles/cytoscape/emit.ts +1264 -0
  636. package/src/styles/cytoscape/index.ts +40 -0
  637. package/src/styles/cytoscape/lexicon.ts +658 -0
  638. package/src/styles/cytoscape/mappings.ts +603 -0
  639. package/src/styles/cytoscape/resolve.ts +521 -0
  640. package/src/styles/cytoscape/translate.ts +237 -0
  641. package/src/styles/defaults.ts +504 -0
  642. package/src/styles/index.ts +57 -0
  643. package/src/styles/internal.ts +17 -0
  644. package/src/styles/io/approximations.ts +47 -0
  645. package/src/styles/io/block.ts +1138 -0
  646. package/src/styles/io/generic.ts +687 -0
  647. package/src/styles/io/index.ts +18 -0
  648. package/src/styles/io/writer.ts +780 -0
  649. package/src/styles/notes.ts +165 -0
  650. package/src/styles/plan/classes.ts +166 -0
  651. package/src/styles/plan/continuous.ts +218 -0
  652. package/src/styles/plan/discrete.ts +165 -0
  653. package/src/styles/plan/families.ts +115 -0
  654. package/src/styles/plan/features.ts +234 -0
  655. package/src/styles/plan/index.ts +7 -0
  656. package/src/styles/plan/plan.ts +1129 -0
  657. package/src/styles/plan/resolve.ts +685 -0
  658. package/src/styles/types.ts +814 -0
  659. package/src/styles/vocabulary.ts +172 -0
  660. package/src/types.ts +76 -1
  661. package/dist/chunks/constants-fT3E8JYY.js.map +0 -1
  662. package/dist/chunks/escape-B62ZGM_a.js.map +0 -1
  663. package/dist/chunks/export-rKLeGQMo.js.map +0 -1
  664. package/dist/chunks/exporter-8hLNemFk.js.map +0 -1
  665. package/dist/chunks/exporter-BWwEuOPT.js.map +0 -1
  666. package/dist/chunks/exporter-RVtXVetw.js.map +0 -1
  667. package/dist/chunks/importer-BbNb7eNg.js.map +0 -1
  668. package/dist/chunks/importer-C98dpSH4.js.map +0 -1
  669. package/dist/chunks/importer-D794XUTe.js.map +0 -1
  670. package/dist/chunks/importer-Dz7tI8Sa.js.map +0 -1
  671. package/dist/chunks/importer-Ht7LNg8L.js.map +0 -1
  672. package/dist/chunks/importer-WrGRZb0N.js.map +0 -1
  673. package/dist/chunks/importer-xZ-3suY1.js.map +0 -1
  674. package/dist/chunks/json-elements-DKSqpNW1.js.map +0 -1
@@ -0,0 +1,1753 @@
1
+ /**
2
+ * JSON styles: each dialect read the way the program that draws it draws it, and a graph's styles written back into
3
+ * each dialect's own style keys.
4
+ *
5
+ * - Cytoscape.js: the stylesheet (an array or a CSS-like text) over the raw element JSON, through graph-io's
6
+ * Cytoscape.js engine, with Cytoscape.js's defaults beneath it; an element's own `style` is a bypass. Cytoscape
7
+ * desktop's export without a stylesheet gets Cytoscape desktop's default style instead.
8
+ * - graphology: the keys sigma.js draws (`color`, `size`, `label`, `hidden`), with sigma's defaults. Gephi's JSON
9
+ * export for sigma.js is read the same way.
10
+ * - vis.js: the keys vis-network draws, `options.nodes` and `options.edges` as declared defaults and
11
+ * `options.groups` as group rules, with vis-network's defaults, its palette for groups the file does not define,
12
+ * and an edge without a color of its own in its source node's border color.
13
+ * - NetworkX node-link: no style keys, NetworkX's drawing defaults.
14
+ *
15
+ * Writing: Cytoscape.js gets a stylesheet with the element data its selectors read and a bypass where no rule gives
16
+ * the value; graphology and vis.js get their per-element keys; node-link, d3 and JGF only the `graphty.styles` block
17
+ * and the tagged per-element values. The block is a graph attribute where the dialect has graph attributes
18
+ * (node-link, JGF, graphology) and a top-level key elsewhere (d3, vis.js, Cytoscape.js).
19
+ */
20
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
21
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
22
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
23
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
24
+ };
25
+ var _Replaced_counts;
26
+ import { canonColor } from "../../styles/canon/color.js";
27
+ import { canonEnum } from "../../styles/canon/enums.js";
28
+ import { canonBoolean, canonNumber, canonOpacity } from "../../styles/canon/number.js";
29
+ import { canonText } from "../../styles/canon/text.js";
30
+ import { STYLE_ISSUE } from "../../styles/codes.js";
31
+ import { cytoscapeJsStyles } from "../../styles/cyjs/cascade.js";
32
+ import { cyjsHoldsExactly, CYTOSCAPE_IMPORT_KEY, toCytoscapeStylesheet, } from "../../styles/cyjs/emit.js";
33
+ import { CYJS_EDGE_PROPERTIES, CYJS_NODE_PROPERTIES } from "../../styles/cyjs/mappers.js";
34
+ import { toolDefaults } from "../../styles/defaults.js";
35
+ import { StyleApproximations } from "../../styles/io/approximations.js";
36
+ import { blockStyles, parseStyleBlock, STYLE_BLOCK_NAME } from "../../styles/io/block.js";
37
+ import { StyleNotes } from "../../styles/notes.js";
38
+ import { styleFingerprint } from "../../styles/plan/features.js";
39
+ import { plainCell, resolveStyles } from "../../styles/plan/resolve.js";
40
+ import { isJsonObject } from "./dialect.js";
41
+ const TARGETS = ["node", "edge"];
42
+ // ============================================================ reading
43
+ /**
44
+ * The styles of a JSON document, read by its dialect's reader from what the import kept.
45
+ * @param snapshot - the graph the import built
46
+ * @param context - the work budget and what the import kept
47
+ * @returns the styles, or null when the dialect has none (a block held as a graph attribute is read by graph-io)
48
+ */
49
+ export function jsonStyles(snapshot, context) {
50
+ const src = context.kept;
51
+ if (!isJsonObject(src)) {
52
+ return null;
53
+ }
54
+ switch (src.dialect) {
55
+ case "cytoscape":
56
+ return cytoscapeStyles(snapshot, src, context);
57
+ case "graphology":
58
+ return graphologyStyles(snapshot, src, context);
59
+ case "vis":
60
+ return visStyles(snapshot, src, context);
61
+ case "node-link":
62
+ if (src.networkx === true) {
63
+ return networkxStyles(snapshot);
64
+ }
65
+ return src.block === null ? null : { canonical: true, block: src.block };
66
+ default:
67
+ return src.block === null ? null : { canonical: true, block: src.block };
68
+ }
69
+ }
70
+ /**
71
+ * Cytoscape.js: the stylesheet over the raw elements. A file graphty wrote is read without Cytoscape.js's own default
72
+ * rules (its block holds graphty's defaults); Cytoscape desktop's export without a stylesheet gets Cytoscape desktop's
73
+ * default style.
74
+ * @param snapshot - the graph
75
+ * @param src - what the import kept
76
+ * @param context - the work budget
77
+ * @returns the styles
78
+ */
79
+ function cytoscapeStyles(snapshot, src, context) {
80
+ const sheetless = (src.style === undefined || src.style === null) && src.generatedBy?.startsWith("cytoscape-") === true;
81
+ // a file graphty wrote: its stylesheet states graphty's styles, beneath which graphty draws its own defaults
82
+ const graphty = src.block !== null && parseStyleBlock(src.block, styleFingerprint(snapshot)).ok;
83
+ const read = cytoscapeJsStyles({
84
+ elements: withGeneratedIds(src.elements, src.generatedIds),
85
+ style: sheetless ? [] : (src.style ?? []),
86
+ snapshot,
87
+ toolDefaults: !graphty && !sheetless,
88
+ budget: context.budget,
89
+ signal: context.signal,
90
+ });
91
+ if (!("canonical" in read)) {
92
+ return read;
93
+ }
94
+ let tool = "cytoscape-js";
95
+ if (graphty) {
96
+ tool = null;
97
+ exactFromBlock(snapshot, src.block, { node: (read.node?.values ?? {}), edge: (read.edge?.values ?? {}) }, CYJS_WRITTEN, cyjsHoldsExactly);
98
+ }
99
+ else if (sheetless) {
100
+ tool = "cytoscape";
101
+ }
102
+ return { ...read, tool, block: src.block };
103
+ }
104
+ /**
105
+ * Cytoscape.js trims every text it draws: a label with blanks around it reads back trimmed.
106
+ * @param property - the text property
107
+ * @returns what a written value reads back as
108
+ */
109
+ const trimmed = (property) => (want) => {
110
+ const v = want(property);
111
+ return typeof v === "string" ? v.trim() : null;
112
+ };
113
+ /** The text properties Cytoscape.js trims. */
114
+ const CYJS_TEXT = {
115
+ node: ["label"],
116
+ edge: ["label", "sourceLabel", "targetLabel"],
117
+ };
118
+ const CYJS_WRITTEN = {
119
+ node: Object.fromEntries(CYJS_TEXT.node.map((p) => [p, trimmed(p)])),
120
+ edge: {
121
+ ...Object.fromEntries(CYJS_TEXT.edge.map((p) => [p, trimmed(p)])),
122
+ // Cytoscape.js draws a loop curved whatever its curve style says
123
+ curved: (want, e, snapshot) => snapshot.edgeSource(e) === snapshot.edgeTarget(e) && want("curved") !== null ? true : want("curved"),
124
+ },
125
+ };
126
+ /**
127
+ * The elements with the ids graph-io gave the nodes that have none, so the engine matches them to the graph.
128
+ * @param elements - the elements as the file holds them
129
+ * @param ids - the generated ids
130
+ * @returns the elements, copied only where an id is added
131
+ */
132
+ function withGeneratedIds(elements, ids) {
133
+ if (ids === undefined || ids.size === 0) {
134
+ return elements;
135
+ }
136
+ const patch = (e) => {
137
+ const id = isJsonObject(e) ? ids.get(e) : undefined;
138
+ return id === undefined || !isJsonObject(e) ? e : { ...e, data: { ...e.data, id } };
139
+ };
140
+ if (Array.isArray(elements)) {
141
+ return elements.map(patch);
142
+ }
143
+ if (isJsonObject(elements) && Array.isArray(elements.nodes)) {
144
+ return { ...elements, nodes: elements.nodes.map(patch) };
145
+ }
146
+ return elements;
147
+ }
148
+ /**
149
+ * NetworkX node-link: no style keys, NetworkX's drawing defaults, and an arrow at the target of every directed edge.
150
+ * @param snapshot - the graph
151
+ * @returns the styles
152
+ */
153
+ function networkxStyles(snapshot) {
154
+ return {
155
+ canonical: true,
156
+ dialect: null,
157
+ tool: "networkx",
158
+ units: "px",
159
+ node: { values: {} },
160
+ edge: directedArrows(snapshot),
161
+ };
162
+ }
163
+ /**
164
+ * The edge output marking directed edges with the tool's target arrow.
165
+ * @param snapshot - the graph
166
+ * @returns the edge output
167
+ */
168
+ function directedArrows(snapshot) {
169
+ if (!snapshot.directed || snapshot.edgeCount === 0) {
170
+ return { values: {}, rules: [], columns: new Map() };
171
+ }
172
+ const col = snapshot.edges.byRole("directed");
173
+ const flags = Array.from({ length: snapshot.edgeCount }, (_v, e) => col === null || plainCell(col.value(e)) !== false ? true : null);
174
+ return {
175
+ values: {},
176
+ rules: [
177
+ {
178
+ id: "edge.tool.arrow",
179
+ target: "edge",
180
+ role: "group",
181
+ origin: "tool",
182
+ where: { has: { style: "directed" } },
183
+ set: { targetArrow: "triangle" },
184
+ },
185
+ ],
186
+ columns: new Map([["directed", flags]]),
187
+ };
188
+ }
189
+ /**
190
+ * One element's values of a column, with a reader per value.
191
+ * @param snapshot - the graph
192
+ * @param target - nodes or edges
193
+ * @param name - the column
194
+ * @returns the cell reader, or null when the graph has no such column
195
+ */
196
+ function cells(snapshot, target, name) {
197
+ const table = target === "node" ? snapshot.nodes : snapshot.edges;
198
+ return table.has(name) ? (i) => plainCell(table.value(name, i)) : null;
199
+ }
200
+ /**
201
+ * A values table that makes each property's column on first use.
202
+ * @param n - the element count
203
+ * @returns the values and a setter
204
+ */
205
+ function valuesOf(n) {
206
+ const values = {};
207
+ return {
208
+ values,
209
+ put: (p, i, v) => {
210
+ if (v !== null) {
211
+ setValue(values, p, n, i, v);
212
+ }
213
+ },
214
+ };
215
+ }
216
+ /**
217
+ * Sets one element's value of a property, making the property's column on first use.
218
+ * @param values - the values per property
219
+ * @param property - the property
220
+ * @param n - the element count
221
+ * @param i - the element
222
+ * @param v - the value; null clears it
223
+ */
224
+ function setValue(values, property, n, i, v) {
225
+ values[property] ?? (values[property] = new Array(n).fill(null));
226
+ values[property][i] = v;
227
+ }
228
+ /**
229
+ * graphology: the keys sigma.js draws, with sigma's defaults.
230
+ * @param snapshot - the graph
231
+ * @param src - what the import kept
232
+ * @param context - the work budget
233
+ * @returns the styles
234
+ */
235
+ function graphologyStyles(snapshot, src, context) {
236
+ const notes = new StyleNotes();
237
+ const out = { node: {}, edge: {} };
238
+ const readFrom = { node: [], edge: [] };
239
+ for (const target of TARGETS) {
240
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
241
+ const { values, put } = valuesOf(n);
242
+ const keys = {
243
+ color: cells(snapshot, target, "color"),
244
+ size: cells(snapshot, target, "size"),
245
+ label: cells(snapshot, target, "label"),
246
+ hidden: cells(snapshot, target, "hidden"),
247
+ };
248
+ readFrom[target].push(...Object.entries(keys).flatMap(([name, c]) => (c === null ? [] : [name])));
249
+ for (let i = 0; i < n; i++) {
250
+ const site = (property) => ({
251
+ notes,
252
+ target,
253
+ property,
254
+ element: i,
255
+ budget: context.budget,
256
+ });
257
+ readSigmaRow(keys, target, i, put, site);
258
+ }
259
+ out[target] = values;
260
+ }
261
+ exactFromBlock(snapshot, blockText(snapshot, src), out, GRAPHOLOGY_WRITTEN);
262
+ return {
263
+ canonical: true,
264
+ dialect: "graphology",
265
+ tool: "sigma",
266
+ opacityInColor: true,
267
+ units: "relative",
268
+ node: { values: out.node },
269
+ edge: { values: out.edge },
270
+ notes: notes.list(),
271
+ readFrom,
272
+ };
273
+ }
274
+ /**
275
+ * Reads one element's sigma.js keys.
276
+ * @param keys - the cell readers
277
+ * @param target - nodes or edges
278
+ * @param i - the element
279
+ * @param put - the setter
280
+ * @param site - where a value of a property was read
281
+ */
282
+ function readSigmaRow(keys, target, i, put, site) {
283
+ const { color, size, label, hidden } = keys;
284
+ if (color !== null) {
285
+ const [fill, opacity] = target === "node" ? ["fill", "fillOpacity"] : ["color", "opacity"];
286
+ putColor(put, fill, opacity, i, color(i), site(fill));
287
+ }
288
+ if (size !== null) {
289
+ const v = canonNumber(size(i), site("width"));
290
+ put("width", i, v);
291
+ if (target === "node") {
292
+ put("height", i, v);
293
+ }
294
+ }
295
+ if (label !== null) {
296
+ put("label", i, canonText(label(i), site("label")));
297
+ }
298
+ if (hidden !== null && canonBoolean(hidden(i), site("visible")) === true) {
299
+ put("visible", i, false);
300
+ }
301
+ }
302
+ /**
303
+ * A CSS color into a property and its opacity.
304
+ * @param put - the setter
305
+ * @param property - the color property
306
+ * @param opacity - its opacity property, or null when it has none
307
+ * @param i - the element
308
+ * @param raw - the value
309
+ * @param site - where it was read
310
+ */
311
+ function putColor(put, property, opacity, i, raw, site) {
312
+ if (raw === null || raw === undefined || raw === "") {
313
+ return;
314
+ }
315
+ const c = canonColor(raw, "css", site);
316
+ if (c === null) {
317
+ return;
318
+ }
319
+ put(property, i, c.color);
320
+ if (c.alpha < 1) {
321
+ if (opacity === null) {
322
+ site.notes.add(STYLE_ISSUE.ALPHA_DROPPED, site.target, property, { sample: raw, element: i });
323
+ }
324
+ else {
325
+ put(opacity, i, c.alpha);
326
+ }
327
+ }
328
+ }
329
+ /**
330
+ * The text of the block a document holds, as a top-level key or as a graph attribute, or null.
331
+ * @param snapshot - the graph
332
+ * @param src - what the import kept
333
+ * @returns the block's text
334
+ */
335
+ function blockText(snapshot, src) {
336
+ if (src.block !== null) {
337
+ return src.block;
338
+ }
339
+ if (!snapshot.graph.has(STYLE_BLOCK_NAME)) {
340
+ return null;
341
+ }
342
+ const v = plainCell(snapshot.graph.value(STYLE_BLOCK_NAME, 0));
343
+ return typeof v === "string" ? v : null;
344
+ }
345
+ /**
346
+ * For a file graphty wrote: where a native value is what the writer writes for the block's value (a width and a
347
+ * height written as one size, a shape written as the nearest one the dialect has), the block's exact value is the
348
+ * truth, so a re-import gives the same rules. A value another program changed stays the truth.
349
+ * @param snapshot - the graph
350
+ * @param text - the block's text, or null
351
+ * @param values - the native values per target, changed in place
352
+ * @param written - what the writer writes for each approximated property
353
+ * @param holdsExactly - whether the dialect holds a value as it is; where it does not, the native value tells
354
+ * nothing about the block's (the writer never wrote it), so the block's value is the truth
355
+ */
356
+ function exactFromBlock(snapshot, text, values, written, holdsExactly) {
357
+ if (text === null) {
358
+ return;
359
+ }
360
+ const parsed = parseStyleBlock(text, styleFingerprint(snapshot));
361
+ const ex = parsed.ok ? blockStyles(parsed.block, snapshot, "json") : null;
362
+ if (ex === null) {
363
+ return;
364
+ }
365
+ for (const target of TARGETS) {
366
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
367
+ const cache = new Map();
368
+ const resolved = (p) => {
369
+ let r = cache.get(p);
370
+ if (r === undefined) {
371
+ r = resolveStyles(ex, target, p, snapshot);
372
+ cache.set(p, r);
373
+ }
374
+ return r;
375
+ };
376
+ if (holdsExactly !== undefined) {
377
+ const properties = new Set(ex.styles.rules
378
+ .filter((r) => r.target === target)
379
+ .flatMap((r) => [...Object.keys(r.set ?? {}), ...Object.keys(r.map ?? {})]));
380
+ for (const property of properties) {
381
+ const held = (w) => holdsExactly(target, property, w);
382
+ takeUnheld(values[target], property, resolved(property), n, held);
383
+ }
384
+ }
385
+ for (const [property, write] of Object.entries(written[target] ?? {})) {
386
+ takeWritten(values[target], property, n, resolved, write, snapshot);
387
+ }
388
+ }
389
+ }
390
+ /**
391
+ * Takes the block's value of a property wherever the native value is what the writer writes for the block's values.
392
+ * @param column - the native values of the target, changed in place
393
+ * @param property - the property
394
+ * @param n - the element count
395
+ * @param resolved - the block's values of a property
396
+ * @param write - what the writer writes for an element, from the block's values
397
+ * @param snapshot - the graph
398
+ */
399
+ function takeWritten(column, property, n, resolved, write, snapshot) {
400
+ const want = resolved(property);
401
+ for (let i = 0; i < n; i++) {
402
+ const w = want[i];
403
+ const native = column[property]?.[i] ?? null;
404
+ // a native value the writer made from the block's other values (vis.js's one size for a width) is the
405
+ // block's own value, none included
406
+ if (native !== w && native !== null && native === write((p) => resolved(p)[i], i, snapshot)) {
407
+ setValue(column, property, n, i, w);
408
+ }
409
+ }
410
+ }
411
+ /**
412
+ * Takes the block's value of a property wherever the dialect does not hold it exactly.
413
+ * @param values - the native values of the target, changed in place
414
+ * @param property - the property
415
+ * @param want - the block's values
416
+ * @param n - the element count
417
+ * @param held - whether the dialect holds a value exactly
418
+ */
419
+ function takeUnheld(values, property, want, n, held) {
420
+ for (let i = 0; i < n; i++) {
421
+ const w = want[i];
422
+ if (w !== null && !held(w)) {
423
+ setValue(values, property, n, i, w);
424
+ }
425
+ }
426
+ }
427
+ /**
428
+ * One size for a width and a height: the larger, as graphology and vis.js write it.
429
+ * @param want - the block's values of the element
430
+ * @returns the size
431
+ */
432
+ const oneSize = (want) => {
433
+ const w = want("width");
434
+ const h = want("height");
435
+ return typeof w === "number" && typeof h === "number" ? Math.max(w, h) : (w ?? h);
436
+ };
437
+ const GRAPHOLOGY_WRITTEN = { node: { width: oneSize, height: oneSize } };
438
+ // ------------------------------------------------------------ vis.js
439
+ /** vis-network's node shapes that take their size from `size` (the others are sized by their label). */
440
+ const VIS_SIZED = new Set([
441
+ "image",
442
+ "circularImage",
443
+ "diamond",
444
+ "dot",
445
+ "star",
446
+ "triangle",
447
+ "triangleDown",
448
+ "hexagon",
449
+ "square",
450
+ "icon",
451
+ ]);
452
+ /**
453
+ * vis-network's palette for a group the file does not define, in the order groups first appear (vis-network
454
+ * 10.1.2, `Groups._defaultGroups`): border, background.
455
+ */
456
+ const VIS_GROUP_PALETTE = [
457
+ ["#2B7CE9", "#97C2FC"],
458
+ ["#FFA500", "#FFFF00"],
459
+ ["#FA0A10", "#FB7E81"],
460
+ ["#41A906", "#7BE141"],
461
+ ["#E129F0", "#EB7DF4"],
462
+ ["#7C29F0", "#AD85E4"],
463
+ ["#C37F00", "#FFA807"],
464
+ ["#4220FB", "#6E6EFD"],
465
+ ["#FD5A77", "#FFC0CB"],
466
+ ["#4AD63A", "#C2FABC"],
467
+ ["#990000", "#EE0000"],
468
+ ["#FF6000", "#FF6000"],
469
+ ["#97C2FC", "#2B7CE9"],
470
+ ["#399605", "#255C03"],
471
+ ["#B70054", "#FF007E"],
472
+ ["#AD85E4", "#7C29F0"],
473
+ ["#4557FA", "#000EA1"],
474
+ ["#FFC0CB", "#FD5A77"],
475
+ ["#C2FABC", "#74D66A"],
476
+ ["#EE0000", "#990000"],
477
+ ];
478
+ /** vis-network's edge color when an edge inherits none (vis-network 10.1.2, `color.color`). */
479
+ const VIS_EDGE_COLOR = "#848484";
480
+ /**
481
+ * vis-network's reading of a node color given as text (vis-util `parseColor`): a hex or `rgb()` color gets a border
482
+ * 20% darker and 25% more saturated; any other text is both.
483
+ * @param text - the color
484
+ * @returns the background and the border
485
+ */
486
+ function visParseColor(text) {
487
+ let hex = text;
488
+ const rgb = /^rgb\( *(\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3}) *\)$/i.exec(text);
489
+ if (rgb?.slice(1).every((c) => Number(c) <= 255)) {
490
+ hex = `#${((1 << 24) + (Number(rgb[1]) << 16) + (Number(rgb[2]) << 8) + Number(rgb[3])).toString(16).slice(1)}`;
491
+ }
492
+ if (!/^#([0-9a-f]{6}|[0-9a-f]{3})$/i.test(hex)) {
493
+ return { background: text, border: text };
494
+ }
495
+ const full = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;
496
+ return { background: full, border: visBorder(full) };
497
+ }
498
+ /**
499
+ * vis-util's border of a background color: 20% darker and 25% more saturated, through HSV.
500
+ * @param full - the background, `#rrggbb`
501
+ * @returns the border, `#rrggbb`
502
+ */
503
+ function visBorder(full) {
504
+ const n = Number.parseInt(full.slice(1), 16);
505
+ const [r, g, b] = [(n >> 16) & 255, (n >> 8) & 255, n & 255].map((c) => c / 255);
506
+ const max = Math.max(r, g, b);
507
+ const min = Math.min(r, g, b);
508
+ let h = 0;
509
+ let s = 0;
510
+ if (max !== min) {
511
+ let d = b - r;
512
+ let k = 5;
513
+ if (r === min) {
514
+ d = g - b;
515
+ k = 3;
516
+ }
517
+ else if (b === min) {
518
+ d = r - g;
519
+ k = 1;
520
+ }
521
+ h = (60 * (k - d / (max - min))) / 360;
522
+ s = (max - min) / max;
523
+ }
524
+ const sv = Math.min(1, s * 1.25);
525
+ const vv = max * 0.8;
526
+ const i = Math.floor(h * 6);
527
+ const f = h * 6 - i;
528
+ const p = vv * (1 - sv);
529
+ const q = vv * (1 - f * sv);
530
+ const t = vv * (1 - (1 - f) * sv);
531
+ const rgbOut = [
532
+ [vv, t, p],
533
+ [q, vv, p],
534
+ [p, vv, t],
535
+ [p, q, vv],
536
+ [t, p, vv],
537
+ [vv, p, q],
538
+ ][i % 6].map((c) => Math.floor(c * 255));
539
+ return `#${((1 << 24) + (rgbOut[0] << 16) + (rgbOut[1] << 8) + rgbOut[2]).toString(16).slice(1)}`;
540
+ }
541
+ /**
542
+ * The vis.js options of one node or edge record (or of `options.nodes`, `options.edges`, a group) as a layer.
543
+ * @param o - the options
544
+ * @param target - nodes or edges
545
+ * @returns the layer
546
+ */
547
+ function visLayer(o, target) {
548
+ if (!isJsonObject(o)) {
549
+ return {};
550
+ }
551
+ const layer = {};
552
+ const set = (k, v) => {
553
+ if (v !== undefined && v !== null) {
554
+ layer[k] = v;
555
+ }
556
+ };
557
+ if (target === "node") {
558
+ visNodeLayer(o, set);
559
+ }
560
+ else {
561
+ visEdgeLayer(o, set);
562
+ }
563
+ set("hidden", o.hidden);
564
+ set("label", o.label);
565
+ set("title", o.title);
566
+ visFontLayer(o.font, set);
567
+ return layer;
568
+ }
569
+ /**
570
+ * The node keys of a vis.js options object: a color given as text has vis-util's darker border.
571
+ * @param o - the options
572
+ * @param set - the layer's setter
573
+ */
574
+ function visNodeLayer(o, set) {
575
+ const { color } = o;
576
+ if (typeof color === "string") {
577
+ const parsed = visParseColor(color.trim());
578
+ set("fill", parsed.background);
579
+ set("border", parsed.border);
580
+ }
581
+ else if (isJsonObject(color)) {
582
+ set("fill", color.background);
583
+ set("border", color.border);
584
+ }
585
+ set("shape", o.shape);
586
+ set("size", o.size);
587
+ set("borderWidth", o.borderWidth);
588
+ set("opacity", o.opacity);
589
+ }
590
+ /**
591
+ * The edge keys of a vis.js options object: a color of its own stops the edge inheriting its node's.
592
+ * @param o - the options
593
+ * @param set - the layer's setter
594
+ */
595
+ function visEdgeLayer(o, set) {
596
+ const { color } = o;
597
+ if (typeof color === "string") {
598
+ set("edgeColor", color);
599
+ set("inherit", false);
600
+ }
601
+ else if (isJsonObject(color)) {
602
+ set("edgeColor", color.color);
603
+ set("edgeOpacity", color.opacity);
604
+ const own = color.color !== undefined || color.highlight !== undefined || color.hover !== undefined;
605
+ set("inherit", own ? false : color.inherit);
606
+ }
607
+ set("width", o.width);
608
+ set("dashes", o.dashes);
609
+ set("arrows", o.arrows);
610
+ }
611
+ /**
612
+ * The font keys of a vis.js options object: an object, or text like `"14px arial red"`.
613
+ * @param font - the `font` value
614
+ * @param set - the layer's setter
615
+ */
616
+ function visFontLayer(font, set) {
617
+ if (isJsonObject(font)) {
618
+ set("fontColor", font.color);
619
+ set("fontSize", font.size);
620
+ set("fontFace", font.face);
621
+ }
622
+ else if (typeof font === "string") {
623
+ const m = /^\s*(\d+(?:\.\d+)?)(?:px)?\s+(\S+)(?:\s+(\S+))?/.exec(font.slice(0, 256));
624
+ if (m !== null) {
625
+ set("fontSize", Number(m[1]));
626
+ set("fontFace", m[2]);
627
+ set("fontColor", m[3]);
628
+ }
629
+ }
630
+ }
631
+ /**
632
+ * The canonical values of one vis.js layer.
633
+ * @param layer - the layer
634
+ * @param target - nodes or edges
635
+ * @param site - where its values are read
636
+ * @param sized - nodes: whether the shape takes its size from `size`
637
+ * @returns the values
638
+ */
639
+ function visValues(layer, target, site, sized) {
640
+ const out = {};
641
+ const put = (p, v) => {
642
+ if (v !== null) {
643
+ out[p] = v;
644
+ }
645
+ };
646
+ const color = (p, opacity, raw) => {
647
+ if (raw === undefined || raw === null || raw === "") {
648
+ return;
649
+ }
650
+ const c = canonColor(raw, "vis", site(p));
651
+ if (c !== null) {
652
+ put(p, c.color);
653
+ if (c.alpha < 1 && opacity !== null) {
654
+ put(opacity, c.alpha);
655
+ }
656
+ }
657
+ };
658
+ if (target === "node") {
659
+ color("fill", "fillOpacity", layer.fill);
660
+ color("borderColor", null, layer.border);
661
+ visNodeValues(layer, sized, put, site);
662
+ }
663
+ else {
664
+ color("color", "opacity", layer.edgeColor);
665
+ visEdgeValues(layer, put, site);
666
+ }
667
+ if (layer.hidden !== undefined && canonBoolean(layer.hidden, site("visible")) === true) {
668
+ put("visible", false);
669
+ }
670
+ if (layer.label !== undefined) {
671
+ put("label", canonText(layer.label, site("label")));
672
+ }
673
+ if (layer.title !== undefined) {
674
+ put("tooltip", canonText(layer.title, site("tooltip")));
675
+ }
676
+ color("labelColor", null, layer.fontColor);
677
+ if (layer.fontSize !== undefined) {
678
+ put("labelSize", canonNumber(layer.fontSize, site("labelSize")));
679
+ }
680
+ if (layer.fontFace !== undefined) {
681
+ put("labelFont", canonText(layer.fontFace, site("labelFont")));
682
+ }
683
+ return out;
684
+ }
685
+ /**
686
+ * The node values of a vis.js layer besides its colors.
687
+ * @param layer - the layer
688
+ * @param sized - whether the shape takes its size from `size`
689
+ * @param put - the row's setter
690
+ * @param site - where its values are read
691
+ */
692
+ function visNodeValues(layer, sized, put, site) {
693
+ if (layer.shape !== undefined) {
694
+ put("shape", canonEnum("shape", layer.shape, "vis", site("shape")));
695
+ }
696
+ if (sized && layer.size !== undefined) {
697
+ const v = canonNumber(layer.size, site("width"));
698
+ put("width", v);
699
+ put("height", v);
700
+ }
701
+ if (layer.borderWidth !== undefined) {
702
+ put("borderWidth", canonNumber(layer.borderWidth, site("borderWidth")));
703
+ }
704
+ if (layer.opacity !== undefined) {
705
+ put("opacity", canonOpacity(layer.opacity, "vis", site("opacity")));
706
+ }
707
+ }
708
+ /**
709
+ * The edge values of a vis.js layer besides its color.
710
+ * @param layer - the layer
711
+ * @param put - the row's setter
712
+ * @param site - where its values are read
713
+ */
714
+ function visEdgeValues(layer, put, site) {
715
+ if (layer.edgeOpacity !== undefined) {
716
+ put("opacity", canonOpacity(layer.edgeOpacity, "vis", site("opacity")));
717
+ }
718
+ if (layer.width !== undefined) {
719
+ put("width", canonNumber(layer.width, site("width")));
720
+ }
721
+ if (layer.dashes !== undefined) {
722
+ put("lineStyle", layer.dashes === false || layer.dashes === "false" ? "solid" : "dashed");
723
+ }
724
+ if (layer.arrows !== undefined) {
725
+ const [to, from] = visArrows(layer.arrows, site);
726
+ put("targetArrow", to);
727
+ put("sourceArrow", from);
728
+ }
729
+ }
730
+ /**
731
+ * vis.js `arrows` as the target and source arrows: `"to"`, `"to, from"`, or `{ to: true | { enabled, type } }`.
732
+ * @param arrows - the value
733
+ * @param site - where it is read
734
+ * @returns the target arrow and the source arrow
735
+ */
736
+ function visArrows(arrows, site) {
737
+ const end = (name, property) => {
738
+ if (typeof arrows === "string") {
739
+ return new RegExp(String.raw `\b${name}\b`).test(arrows.slice(0, 256)) ? "triangle" : "none";
740
+ }
741
+ if (!isJsonObject(arrows)) {
742
+ return null;
743
+ }
744
+ const a = arrows[name];
745
+ if (a === true) {
746
+ return "triangle";
747
+ }
748
+ if (!isJsonObject(a) || a.enabled === false) {
749
+ return "none";
750
+ }
751
+ return canonEnum("arrow", a.type ?? "arrow", "vis", site(property));
752
+ };
753
+ return [end("to", "targetArrow"), end("from", "sourceArrow")];
754
+ }
755
+ /**
756
+ * vis.js: the per-element keys over the file's groups and `options.nodes` / `options.edges`, beneath them
757
+ * vis-network's defaults. The defaults and groups the file declares become declared rules; a group the file does not
758
+ * define gets vis-network's palette, as a rule of the tool's; an edge without a color of its own takes its source
759
+ * node's border color (its target's under `inherit: "to"`).
760
+ * @param snapshot - the graph
761
+ * @param src - what the import kept
762
+ * @param context - the work budget
763
+ * @returns the styles
764
+ */
765
+ function visStyles(snapshot, src, context) {
766
+ const notes = new StyleNotes();
767
+ const options = isJsonObject(src.options) ? src.options : {};
768
+ const n = snapshot.nodeCount;
769
+ const ruleSite = (target) => (property) => ({ notes, target, property });
770
+ const nodeRules = [];
771
+ const nodeColumns = new Map();
772
+ // the node defaults and groups the file declares
773
+ const nodeDefaults = visLayer(options.nodes, "node");
774
+ const groupCol = cells(snapshot, "node", "group");
775
+ const groupOf = (i) => {
776
+ const g = groupCol?.(i);
777
+ return typeof g === "string" || typeof g === "number" ? String(g) : null;
778
+ };
779
+ const { groupLayers, paletteRows } = visGroupLayers(n, groupOf, visGroupDefs(src, options));
780
+ context.budget.spend("node", n);
781
+ // what vis-network draws per node: its own keys over its group over options.nodes
782
+ const node = valuesOf(n);
783
+ const records = nodeRecords(snapshot);
784
+ const rawShape = (layer) => (typeof layer.shape === "string" ? layer.shape : null);
785
+ for (let i = 0; i < n; i++) {
786
+ const g = groupOf(i);
787
+ const own = records(i);
788
+ const group = g === null ? {} : (groupLayers.get(g) ?? {});
789
+ const shape = rawShape(own) ?? rawShape(group) ?? rawShape(nodeDefaults) ?? "ellipse";
790
+ const site = (property) => ({
791
+ notes,
792
+ target: "node",
793
+ property,
794
+ element: i,
795
+ budget: context.budget,
796
+ });
797
+ const merged = { ...nodeDefaults, ...group, ...own };
798
+ for (const [p, v] of Object.entries(visValues(merged, "node", site, VIS_SIZED.has(shape)))) {
799
+ node.put(p, i, v);
800
+ }
801
+ }
802
+ const declaredNode = visValues(nodeDefaults, "node", ruleSite("node"), true);
803
+ if (Object.keys(declaredNode).length > 0) {
804
+ nodeRules.push(rule("node.vis.defaults", "node", "defaults", "declared", { all: true }, declaredNode));
805
+ }
806
+ let k = 0;
807
+ for (const [g, layer] of groupLayers) {
808
+ const set = paletteRows.get(g) ?? visValues(layer, "node", ruleSite("node"), true);
809
+ if (Object.keys(set).length === 0) {
810
+ continue;
811
+ }
812
+ const key = `group.${String(k)}`;
813
+ nodeColumns.set(key, Array.from({ length: n }, (_v, i) => (groupOf(i) === g ? true : null)));
814
+ const origin = paletteRows.has(g) ? "tool" : "declared";
815
+ const r = rule(`node.vis.group.${String(k++)}`, "node", "group", origin, { has: { style: key } }, set);
816
+ nodeRules.push({ ...r, facts: { names: [[key, g]] } });
817
+ }
818
+ const toolNode = toolDefaults("vis-network")?.node;
819
+ const borderOf = (i) => node.values.borderColor?.[i] ?? toolNode?.borderColor?.value ?? "#2b7ce9";
820
+ const edge = visEdges(snapshot, visLayer(options.edges, "edge"), borderOf, notes, context);
821
+ const values = { node: node.values, edge: edge.values };
822
+ exactFromBlock(snapshot, src.block, values, VIS_WRITTEN);
823
+ return {
824
+ canonical: true,
825
+ dialect: "vis",
826
+ tool: "vis-network",
827
+ opacityInColor: true,
828
+ units: "px",
829
+ node: { values: values.node, rules: nodeRules, columns: nodeColumns },
830
+ edge: { values: values.edge, rules: edge.rules, columns: edge.columns },
831
+ notes: notes.list(),
832
+ block: src.block,
833
+ readFrom: {
834
+ node: VIS_KEYS.node.filter((x) => snapshot.nodes.has(x)),
835
+ edge: VIS_KEYS.edge.filter((x) => snapshot.edges.has(x)),
836
+ },
837
+ };
838
+ }
839
+ /**
840
+ * vis.js: the group definitions, from `options.groups` or a top-level `groups`.
841
+ * @param src - what the import kept
842
+ * @param options - the file's `options`
843
+ * @returns the definitions by group name
844
+ */
845
+ function visGroupDefs(src, options) {
846
+ if (isJsonObject(options.groups)) {
847
+ return options.groups;
848
+ }
849
+ return isJsonObject(src.groups) ? src.groups : {};
850
+ }
851
+ /**
852
+ * vis.js: each group the nodes name, in the order first named, with its layer; a group the file does not define gets
853
+ * vis-network's palette.
854
+ * @param n - the node count
855
+ * @param groupOf - each node's group
856
+ * @param groupDefs - the group definitions
857
+ * @returns the layers by group, and the palette values of the groups that took them
858
+ */
859
+ function visGroupLayers(n, groupOf, groupDefs) {
860
+ const groupLayers = new Map();
861
+ const paletteRows = new Map();
862
+ let palette = 0;
863
+ for (let i = 0; i < n; i++) {
864
+ const g = groupOf(i);
865
+ if (g === null || groupLayers.has(g)) {
866
+ continue;
867
+ }
868
+ if (Object.hasOwn(groupDefs, g)) {
869
+ groupLayers.set(g, visLayer(groupDefs[g], "node"));
870
+ }
871
+ else {
872
+ const [border, background] = VIS_GROUP_PALETTE[palette++ % VIS_GROUP_PALETTE.length];
873
+ groupLayers.set(g, { fill: background, border });
874
+ paletteRows.set(g, { fill: background.toLowerCase(), borderColor: border.toLowerCase() });
875
+ }
876
+ }
877
+ return { groupLayers, paletteRows };
878
+ }
879
+ /**
880
+ * vis.js edges: their own keys over `options.edges`; an edge without a color of its own takes its source node's
881
+ * border color (its target's under `inherit: "to"`).
882
+ * @param snapshot - the graph
883
+ * @param edgeDefaults - `options.edges`
884
+ * @param borderOf - each node's drawn border color
885
+ * @param notes - where problems are noted
886
+ * @param context - the work budget
887
+ * @returns the edge values, rules and style columns
888
+ */
889
+ function visEdges(snapshot, edgeDefaults, borderOf, notes, context) {
890
+ const m = snapshot.edgeCount;
891
+ const edge = valuesOf(m);
892
+ const edgeRecords = elementRecords(snapshot, "edge");
893
+ const inherited = new Array(m).fill(null);
894
+ let inheriting = 0;
895
+ for (let e = 0; e < m; e++) {
896
+ const own = edgeRecords(e);
897
+ const merged = { ...edgeDefaults, ...own };
898
+ const site = (property) => ({
899
+ notes,
900
+ target: "edge",
901
+ property,
902
+ element: e,
903
+ budget: context.budget,
904
+ });
905
+ const vals = visValues(merged, "edge", site, true);
906
+ for (const [p, v] of Object.entries(vals)) {
907
+ edge.put(p, e, v);
908
+ }
909
+ const inherit = own.inherit ?? edgeDefaults.inherit ?? "from";
910
+ if (inherit === false || inherit === "false") {
911
+ if (vals.color === undefined) {
912
+ edge.put("color", e, VIS_EDGE_COLOR);
913
+ }
914
+ continue;
915
+ }
916
+ if (inherit === "both") {
917
+ notes.add(STYLE_ISSUE.GRADIENT, "edge", "color", { sample: "inherit both", element: e });
918
+ }
919
+ inherited[e] = borderOf(inherit === "to" ? snapshot.edgeTarget(e) : snapshot.edgeSource(e));
920
+ inheriting++;
921
+ }
922
+ context.budget.spend("edge", m);
923
+ const edgeRules = [];
924
+ const edgeColumns = new Map();
925
+ const declaredEdge = visValues(edgeDefaults, "edge", (property) => ({ notes, target: "edge", property }), true);
926
+ if (Object.keys(declaredEdge).length > 0) {
927
+ edgeRules.push(rule("edge.vis.defaults", "edge", "defaults", "declared", { all: true }, declaredEdge));
928
+ }
929
+ if (inheriting > 0) {
930
+ // vis-network draws such an edge in its source node's color. graphty-element cannot bind an edge's color to
931
+ // its source node's drawn color yet, so the color is frozen here; replace this column with that binding once
932
+ // the element has it (tracking issue "graphty-element: bind an edge's color to its source node's drawn color").
933
+ edgeColumns.set("source-color", inherited);
934
+ edgeRules.push({
935
+ id: "edge.tool.source-color",
936
+ target: "edge",
937
+ role: "passthrough",
938
+ origin: "tool",
939
+ where: { has: { style: "source-color" } },
940
+ map: { color: { kind: "passthrough", by: { style: "source-color" } } },
941
+ facts: { elements: inheriting, reason: "SOURCE_NODE_COLOR" },
942
+ });
943
+ }
944
+ return { values: edge.values, rules: edgeRules, columns: edgeColumns };
945
+ }
946
+ /** The vis.js keys the reader reads, per target. */
947
+ const VIS_KEYS = {
948
+ node: ["color", "shape", "size", "borderWidth", "opacity", "hidden", "label", "title", "font"],
949
+ edge: ["color", "width", "dashes", "arrows", "hidden", "label", "title", "font"],
950
+ };
951
+ /**
952
+ * Each node's own vis.js keys as a layer.
953
+ * @param snapshot - the graph
954
+ * @returns the layer of a node
955
+ */
956
+ function nodeRecords(snapshot) {
957
+ return elementRecords(snapshot, "node");
958
+ }
959
+ /**
960
+ * Each element's own vis.js keys as a layer, read from the graph's columns.
961
+ * @param snapshot - the graph
962
+ * @param target - nodes or edges
963
+ * @returns the layer of an element
964
+ */
965
+ function elementRecords(snapshot, target) {
966
+ const readers = VIS_KEYS[target]
967
+ .map((name) => [name, cells(snapshot, target, name)])
968
+ .filter((x) => x[1] !== null);
969
+ return (i) => {
970
+ const record = {};
971
+ for (const [name, read] of readers) {
972
+ const v = read(i);
973
+ if (v !== null) {
974
+ record[name] = v;
975
+ }
976
+ }
977
+ return visLayer(record, target);
978
+ };
979
+ }
980
+ /**
981
+ * A rule.
982
+ * @param id - its id
983
+ * @param target - nodes or edges
984
+ * @param role - what it is
985
+ * @param origin - where it came from
986
+ * @param where - which elements
987
+ * @param set - the values
988
+ * @returns the rule
989
+ */
990
+ function rule(id, target, role, origin, where, set) {
991
+ const values = {};
992
+ for (const [p, v] of Object.entries(set)) {
993
+ if (v !== null) {
994
+ values[p] = v;
995
+ }
996
+ }
997
+ return { id, target, role, origin, where, set: values };
998
+ }
999
+ // ============================================================ writing
1000
+ /** The neutral node shape to vis-network's shape; the boolean says whether it is exact. */
1001
+ const VIS_SHAPES = new Map([
1002
+ ["ellipse", ["dot", true]],
1003
+ ["rectangle", ["square", true]],
1004
+ ["round-rectangle", ["box", true]],
1005
+ ["triangle", ["triangle", true]],
1006
+ ["diamond", ["diamond", true]],
1007
+ ["star", ["star", true]],
1008
+ ["hexagon", ["hexagon", true]],
1009
+ ["none", ["text", true]],
1010
+ ["pentagon", ["hexagon", false]],
1011
+ ["octagon", ["hexagon", false]],
1012
+ ["parallelogram", ["box", false]],
1013
+ ["trapezoid", ["box", false]],
1014
+ ["vee", ["triangle", false]],
1015
+ ]);
1016
+ /** The neutral arrow to vis-network's arrow type; the boolean says whether it is exact. */
1017
+ const VIS_ARROW_TYPES = new Map([
1018
+ ["triangle", ["arrow", true]],
1019
+ ["tee", ["bar", true]],
1020
+ ["circle", ["circle", true]],
1021
+ ["square", ["box", true]],
1022
+ ["crow", ["crow", true]],
1023
+ ["diamond", ["diamond", true]],
1024
+ ["vee", ["vee", true]],
1025
+ ["inverted", ["inv_triangle", true]],
1026
+ ["triangle-open", ["arrow", false]],
1027
+ ["diamond-open", ["diamond", false]],
1028
+ ["circle-open", ["circle", false]],
1029
+ ["half", ["arrow", false]],
1030
+ ]);
1031
+ /**
1032
+ * A neutral shape as vis-network's: the shape, and whether it is exact.
1033
+ * @param shape - the neutral shape
1034
+ * @returns the vis-network shape and whether it is exact
1035
+ */
1036
+ function visShape(shape) {
1037
+ const known = VIS_SHAPES.get(shape);
1038
+ if (known !== undefined) {
1039
+ return known;
1040
+ }
1041
+ return shape.startsWith("other:") ? [shape.slice(6), true] : ["dot", false];
1042
+ }
1043
+ /**
1044
+ * A neutral arrow as vis-network's arrow type: the type (null for none), and whether it is exact.
1045
+ * @param arrow - the neutral arrow
1046
+ * @returns the type and whether it is exact
1047
+ */
1048
+ function visArrowType(arrow) {
1049
+ if (arrow === "none") {
1050
+ return [null, true];
1051
+ }
1052
+ const known = VIS_ARROW_TYPES.get(arrow);
1053
+ if (known !== undefined) {
1054
+ return known;
1055
+ }
1056
+ return arrow.startsWith("other:") ? [arrow.slice(6), true] : ["arrow", false];
1057
+ }
1058
+ /** What reading a written vis.js file gives back for the values vis.js holds only approximately. */
1059
+ /**
1060
+ * A node size as a written vis.js file gives it back: one size for both, and none for a shape vis-network sizes by
1061
+ * its label.
1062
+ * @param want - the block's values of the element
1063
+ * @returns the size read back
1064
+ */
1065
+ const visSize = (want) => {
1066
+ const s = want("shape");
1067
+ const shape = typeof s === "string" ? visShape(s)[0] : "ellipse";
1068
+ return VIS_SIZED.has(shape) ? oneSize(want) : null;
1069
+ };
1070
+ const VIS_WRITTEN = {
1071
+ node: {
1072
+ width: visSize,
1073
+ height: visSize,
1074
+ shape: (want) => {
1075
+ const s = want("shape");
1076
+ if (typeof s !== "string") {
1077
+ return null;
1078
+ }
1079
+ const site = { notes: new StyleNotes(), target: "node", property: "shape" };
1080
+ return canonEnum("shape", visShape(s)[0], "vis", site);
1081
+ },
1082
+ },
1083
+ edge: {
1084
+ lineStyle: (want) => {
1085
+ const s = want("lineStyle");
1086
+ if (s === null) {
1087
+ return null;
1088
+ }
1089
+ return s === "solid" ? "solid" : "dashed";
1090
+ },
1091
+ targetArrow: (want) => arrowBack(want("targetArrow")),
1092
+ sourceArrow: (want) => arrowBack(want("sourceArrow")),
1093
+ },
1094
+ };
1095
+ /**
1096
+ * What a written arrow reads back as.
1097
+ * @param a - the neutral arrow
1098
+ * @returns the arrow read back
1099
+ */
1100
+ function arrowBack(a) {
1101
+ if (typeof a !== "string") {
1102
+ return null;
1103
+ }
1104
+ const [type] = visArrowType(a);
1105
+ const site = { notes: new StyleNotes(), target: "edge", property: "targetArrow" };
1106
+ return type === null ? "none" : canonEnum("arrow", type, "vis", site);
1107
+ }
1108
+ /**
1109
+ * The neutral properties Cytoscape.js holds natively, per target (what the stylesheet emitter writes).
1110
+ * @param map - the emitter's Cytoscape.js properties
1111
+ * @param extra - the neutral properties written by a rule of their own
1112
+ * @returns the properties
1113
+ */
1114
+ function cyjsProperties(map, extra) {
1115
+ const out = new Set();
1116
+ for (const spec of map.values()) {
1117
+ if (!spec.property.startsWith("_")) {
1118
+ out.add(spec.property);
1119
+ }
1120
+ }
1121
+ for (const p of extra) {
1122
+ out.add(p);
1123
+ }
1124
+ return [...out];
1125
+ }
1126
+ /**
1127
+ * The neutral properties each style-writing dialect holds natively. Not part of the published entry points: the
1128
+ * documentation's per-dialect tables read it, through a dynamic import knip cannot follow (hence public).
1129
+ * @public
1130
+ */
1131
+ export const NATIVE = {
1132
+ cytoscape: {
1133
+ node: cyjsProperties(CYJS_NODE_PROPERTIES, ["labelPosition", "labelItalic", "visible"]),
1134
+ edge: cyjsProperties(CYJS_EDGE_PROPERTIES, ["curved", "labelItalic", "visible"]),
1135
+ },
1136
+ graphology: {
1137
+ node: ["fill", "fillOpacity", "width", "height", "label", "visible"],
1138
+ edge: ["color", "opacity", "width", "label", "visible"],
1139
+ },
1140
+ vis: {
1141
+ node: [
1142
+ "fill",
1143
+ "fillOpacity",
1144
+ "borderColor",
1145
+ "borderWidth",
1146
+ "shape",
1147
+ "width",
1148
+ "height",
1149
+ "opacity",
1150
+ "label",
1151
+ "tooltip",
1152
+ "labelColor",
1153
+ "labelSize",
1154
+ "labelFont",
1155
+ "visible",
1156
+ ],
1157
+ edge: [
1158
+ "color",
1159
+ "opacity",
1160
+ "width",
1161
+ "lineStyle",
1162
+ "targetArrow",
1163
+ "sourceArrow",
1164
+ "label",
1165
+ "tooltip",
1166
+ "labelColor",
1167
+ "labelSize",
1168
+ "labelFont",
1169
+ "visible",
1170
+ ],
1171
+ },
1172
+ };
1173
+ /**
1174
+ * What the JSON writer holds natively, over every dialect: Cytoscape.js's stylesheet, vis.js's and graphology's
1175
+ * per-element keys. A dialect that holds less (node-link, d3, JGF hold none) reports the rest from `check()`. The
1176
+ * block goes where each dialect keeps extra data.
1177
+ * @category Built-in formats
1178
+ */
1179
+ export const JSON_STYLE_CAPABILITIES = Object.freeze({
1180
+ node: Object.freeze([
1181
+ ...new Set([...NATIVE.cytoscape.node, ...NATIVE.vis.node, ...NATIVE.graphology.node]),
1182
+ ]),
1183
+ edge: Object.freeze([
1184
+ ...new Set([...NATIVE.cytoscape.edge, ...NATIVE.vis.edge, ...NATIVE.graphology.edge]),
1185
+ ]),
1186
+ block: "native",
1187
+ });
1188
+ /** The graph attribute the block is written as, in the dialects with graph attributes. */
1189
+ const BLOCK_AS_ATTRIBUTE = new Set(["node-link", "jgf", "graphology"]);
1190
+ /**
1191
+ * Works out a JSON export with styles for one dialect.
1192
+ * @param snapshot - the graph handed to the exporter
1193
+ * @param dialect - the dialect written
1194
+ * @param input - the styles, or undefined when none are written
1195
+ * @returns the styled export, or null without styles
1196
+ */
1197
+ export function jsonStyledExport(snapshot, dialect, input) {
1198
+ if (input === undefined) {
1199
+ return null;
1200
+ }
1201
+ const native = dialect === "cytoscape" || dialect === "graphology" || dialect === "vis" ? NATIVE[dialect] : null;
1202
+ const notes = [...notWritten(input, dialect, native), ...rulesNotKept(snapshot, dialect, input)];
1203
+ if (dialect === "obographs") {
1204
+ return { snapshot, topLevelBlock: null, stylesheet: null, groups: null, notes };
1205
+ }
1206
+ const out = snapshot.withColumns();
1207
+ const read = dataColumnsRead(input.rules.styles.rules);
1208
+ for (const [table, target] of [
1209
+ [out.nodes, "node"],
1210
+ [out.edges, "edge"],
1211
+ ]) {
1212
+ removeEarlierStyleKeys(table, dialect, read[target]);
1213
+ for (const [name, col] of input.tags[target]) {
1214
+ setColumn(table, name, col);
1215
+ }
1216
+ }
1217
+ if (out.graph.has(STYLE_BLOCK_NAME)) {
1218
+ out.graph.remove(STYLE_BLOCK_NAME);
1219
+ }
1220
+ if (BLOCK_AS_ATTRIBUTE.has(dialect)) {
1221
+ out.graph.set(STYLE_BLOCK_NAME, [input.block], { dtype: "string" });
1222
+ }
1223
+ let stylesheet = null;
1224
+ const approximated = new StyleApproximations();
1225
+ const replaced = new Replaced(out.nodes);
1226
+ if (dialect === "cytoscape") {
1227
+ const emitted = writeCytoscapeStyles(out, input);
1228
+ ({ stylesheet } = emitted);
1229
+ notes.push(...emitted.notes.map(lossOf));
1230
+ addUntrimmedText(input, approximated);
1231
+ }
1232
+ else if (dialect === "graphology") {
1233
+ writeGraphology(out, input, approximated, replaced);
1234
+ }
1235
+ else if (dialect === "vis") {
1236
+ writeVis(out, input, approximated, replaced);
1237
+ }
1238
+ notes.push(...approximated.notes(`the ${dialect} dialect of JSON`), ...replaced.notes(dialect));
1239
+ return {
1240
+ snapshot: out,
1241
+ topLevelBlock: BLOCK_AS_ATTRIBUTE.has(dialect) ? null : input.block,
1242
+ stylesheet,
1243
+ groups: dialect === "vis" ? visGroups(out) : null,
1244
+ notes,
1245
+ };
1246
+ }
1247
+ /**
1248
+ * W_STYLE_RULES_NOT_KEPT for a dialect that cannot give the rules back: JGF when it changes the node ids' type or
1249
+ * order, OBO Graphs always.
1250
+ * @param snapshot - the graph handed to the exporter
1251
+ * @param dialect - the dialect written
1252
+ * @param input - the styles
1253
+ * @returns the notes
1254
+ */
1255
+ function rulesNotKept(snapshot, dialect, input) {
1256
+ let message = null;
1257
+ if (dialect === "jgf" && !jgfKeepsNodes(snapshot)) {
1258
+ message =
1259
+ "the style rules are not kept: JGF changes the node ids' type or order (number ids become text, integer-like ids are read first), so the graphty.styles block no longer matches the graph read back";
1260
+ }
1261
+ else if (dialect === "obographs") {
1262
+ message = "the style rules are not kept: OBO Graphs has no place for them";
1263
+ }
1264
+ if (message === null) {
1265
+ return [];
1266
+ }
1267
+ return [
1268
+ Object.freeze({
1269
+ code: STYLE_ISSUE.RULES_NOT_KEPT,
1270
+ message,
1271
+ column: null,
1272
+ count: input.rules.styles.rules.length,
1273
+ }),
1274
+ ];
1275
+ }
1276
+ /**
1277
+ * Removes the style values an earlier write left in the data, unless the styles themselves read them as data, and,
1278
+ * for Cytoscape.js, the element style an import kept.
1279
+ * @param table - the node or edge table, changed in place
1280
+ * @param dialect - the dialect written
1281
+ * @param read - the data columns the target's rules read
1282
+ */
1283
+ function removeEarlierStyleKeys(table, dialect, read) {
1284
+ for (const name of table.names()) {
1285
+ const styleKey = name.startsWith("graphty.style.") || name.startsWith("graphty_style_") || name === CYTOSCAPE_IMPORT_KEY;
1286
+ if (styleKey && !read.has(name)) {
1287
+ table.remove(name);
1288
+ }
1289
+ }
1290
+ if (dialect === "cytoscape") {
1291
+ for (const name of ["style#element", "css#element"].filter((c) => table.has(c))) {
1292
+ table.remove(name);
1293
+ }
1294
+ }
1295
+ }
1296
+ /**
1297
+ * Writes the Cytoscape.js element data and bypasses the stylesheet reads.
1298
+ * @param out - the graph written, changed in place
1299
+ * @param input - the styles
1300
+ * @returns what toCytoscapeStylesheet() emitted
1301
+ */
1302
+ function writeCytoscapeStyles(out, input) {
1303
+ // the element data the stylesheet is checked against is the data written: without the style values of an
1304
+ // earlier write, which are not written again
1305
+ const features = {
1306
+ node: input.rules.features.node.filter((f) => !("data" in f.ref) || out.nodes.has(f.ref.data)),
1307
+ edge: input.rules.features.edge.filter((f) => !("data" in f.ref) || out.edges.has(f.ref.data)),
1308
+ };
1309
+ const emitted = toCytoscapeStylesheet({ ...input.rules, features });
1310
+ for (const [table, target] of [
1311
+ [out.nodes, "node"],
1312
+ [out.edges, "edge"],
1313
+ ]) {
1314
+ const rows = emitted.elementData[target];
1315
+ const keys = new Set(rows.flatMap((row) => Object.keys(row ?? {})));
1316
+ for (const key of keys) {
1317
+ setColumn(table, key, rows.map((row) => row?.[key] ?? null));
1318
+ }
1319
+ const bypass = emitted.bypass[target].map((b) => (b === null || Object.keys(b).length === 0 ? null : b));
1320
+ if (bypass.some((b) => b !== null)) {
1321
+ setColumn(table, "style#element", bypass);
1322
+ }
1323
+ }
1324
+ return emitted;
1325
+ }
1326
+ /**
1327
+ * Counts as approximated the text values with leading or trailing white space, which Cytoscape.js trims.
1328
+ * @param input - the styles
1329
+ * @param approximated - where approximations are counted
1330
+ */
1331
+ function addUntrimmedText(input, approximated) {
1332
+ for (const target of TARGETS) {
1333
+ for (const property of CYJS_TEXT[target]) {
1334
+ for (const v of input.picture(target, property)) {
1335
+ if (typeof v === "string" && v.trim() !== v) {
1336
+ approximated.add(target, property, JSON.stringify(v));
1337
+ }
1338
+ }
1339
+ }
1340
+ }
1341
+ }
1342
+ /**
1343
+ * vis.js: one empty group definition per value of the nodes' `group` key, so vis-network draws none of its palette.
1344
+ * @param snapshot - the graph written
1345
+ * @returns the definitions, or null when no node names a group
1346
+ */
1347
+ function visGroups(snapshot) {
1348
+ const column = snapshot.nodes.get("group");
1349
+ if (column === null || column === undefined) {
1350
+ return null;
1351
+ }
1352
+ const groups = new Map();
1353
+ for (let i = 0; i < snapshot.nodeCount; i++) {
1354
+ const value = column.isSet(i) ? column.value(i) : null;
1355
+ if (typeof value === "string" || typeof value === "number") {
1356
+ groups.set(String(value), {});
1357
+ }
1358
+ }
1359
+ return groups.size === 0 ? null : Object.fromEntries(groups);
1360
+ }
1361
+ /**
1362
+ * The data columns rules read, per target.
1363
+ * @param rules - the rules
1364
+ * @returns the column names
1365
+ */
1366
+ function dataColumnsRead(rules) {
1367
+ const out = { node: new Set(), edge: new Set() };
1368
+ for (const rule of rules) {
1369
+ const refs = [
1370
+ ...predicateRefs(rule.where),
1371
+ ...Object.values(rule.map ?? {}).flatMap((m) => (m === undefined ? [] : [m.by])),
1372
+ ];
1373
+ for (const ref of refs) {
1374
+ if ("data" in ref) {
1375
+ out[rule.target].add(ref.data);
1376
+ }
1377
+ }
1378
+ }
1379
+ return out;
1380
+ }
1381
+ /**
1382
+ * The columns a predicate tests.
1383
+ * @param where - the predicate
1384
+ * @returns the column references
1385
+ */
1386
+ function predicateRefs(where) {
1387
+ const refs = [];
1388
+ const stack = [where];
1389
+ while (stack.length > 0) {
1390
+ const p = stack.pop();
1391
+ if ("has" in p) {
1392
+ refs.push(p.has);
1393
+ }
1394
+ else if ("eq" in p) {
1395
+ refs.push(p.eq[0]);
1396
+ }
1397
+ else if ("in" in p) {
1398
+ refs.push(p.in[0]);
1399
+ }
1400
+ else if ("and" in p) {
1401
+ stack.push(...p.and);
1402
+ }
1403
+ else if ("or" in p) {
1404
+ stack.push(...p.or);
1405
+ }
1406
+ else if ("not" in p) {
1407
+ stack.push(p.not);
1408
+ }
1409
+ }
1410
+ return refs;
1411
+ }
1412
+ /**
1413
+ * Whether JGF reads the nodes back with the same ids in the same order: no number ids (JGF keys nodes by text), and
1414
+ * the integer-like ids (which JSON parsers enumerate first, ascending) already first and ascending.
1415
+ * @param snapshot - the graph
1416
+ * @returns true when the block's fingerprint survives
1417
+ */
1418
+ function jgfKeepsNodes(snapshot) {
1419
+ let last = -1;
1420
+ let other = false;
1421
+ for (let i = 0; i < snapshot.nodeCount; i++) {
1422
+ const id = snapshot.ids.idOf(i);
1423
+ if (typeof id === "number") {
1424
+ return false;
1425
+ }
1426
+ if (/^(0|[1-9]\d*)$/.test(id) && Number(id) < 4294967295) {
1427
+ if (other || Number(id) <= last) {
1428
+ return false;
1429
+ }
1430
+ last = Number(id);
1431
+ }
1432
+ else {
1433
+ other = true;
1434
+ }
1435
+ }
1436
+ return true;
1437
+ }
1438
+ /**
1439
+ * W_STYLE_NOT_WRITTEN for each property the styles use that the dialect does not hold but some other dialect does
1440
+ * (graph-io reports the properties no dialect holds).
1441
+ * @param input - the styles
1442
+ * @param dialect - the dialect
1443
+ * @param native - what it holds, or null for none
1444
+ * @returns the notes
1445
+ */
1446
+ function notWritten(input, dialect, native) {
1447
+ const out = [];
1448
+ for (const target of TARGETS) {
1449
+ const all = new Set(JSON_STYLE_CAPABILITIES[target]);
1450
+ const held = new Set(native?.[target] ?? []);
1451
+ const used = new Set();
1452
+ for (const r of input.rules.styles.rules) {
1453
+ if (r.target === target) {
1454
+ for (const p of [...Object.keys(r.set ?? {}), ...Object.keys(r.map ?? {})]) {
1455
+ used.add(p);
1456
+ }
1457
+ }
1458
+ }
1459
+ for (const property of used) {
1460
+ if (!all.has(property) || held.has(property)) {
1461
+ continue;
1462
+ }
1463
+ const count = input.picture(target, property).filter((v) => v !== null).length;
1464
+ out.push(Object.freeze({
1465
+ code: STYLE_ISSUE.NOT_WRITTEN,
1466
+ message: `${target} ${property} is not written: the ${dialect} dialect of JSON has no place for it`,
1467
+ column: null,
1468
+ count,
1469
+ style: Object.freeze({ target, property: property }),
1470
+ }));
1471
+ }
1472
+ }
1473
+ return out;
1474
+ }
1475
+ /**
1476
+ * A style note as a loss note.
1477
+ * @param n - the note
1478
+ * @returns the loss note
1479
+ */
1480
+ function lossOf(n) {
1481
+ return Object.freeze({
1482
+ code: n.code,
1483
+ message: n.message,
1484
+ column: null,
1485
+ count: n.params.count,
1486
+ style: n.params.target === null || n.params.property === null
1487
+ ? undefined
1488
+ : Object.freeze({ target: n.params.target, property: n.params.property }),
1489
+ });
1490
+ }
1491
+ /**
1492
+ * Sets a column, with the dtype its values have: numbers, booleans, text, else JSON.
1493
+ * @param table - the table
1494
+ * @param name - the column
1495
+ * @param values - the values by row, null where unset
1496
+ */
1497
+ function setColumn(table, name, values) {
1498
+ const kinds = new Set(values.filter((v) => v !== null && v !== undefined).map((v) => typeof v));
1499
+ let dtype = "json";
1500
+ if (kinds.size === 1) {
1501
+ if (kinds.has("number")) {
1502
+ dtype = "f64";
1503
+ }
1504
+ else if (kinds.has("boolean")) {
1505
+ dtype = "bool";
1506
+ }
1507
+ else if (kinds.has("string")) {
1508
+ dtype = "string";
1509
+ }
1510
+ }
1511
+ // an unset row is undefined: null is a value in a json column
1512
+ table.set(name, values.map((v) => (v === null ? undefined : v)), { dtype });
1513
+ }
1514
+ /**
1515
+ * Writes a picture into a style key: every element gets the picture's value, and an element the picture gives none
1516
+ * loses the key, so a program reading the file draws what graphty draws. A value the column held before that differs
1517
+ * is counted, for the loss note.
1518
+ * @param table - the table
1519
+ * @param name - the column
1520
+ * @param values - the picture, null where it has no value
1521
+ * @param replaced - counts the values replaced, per column
1522
+ */
1523
+ function writeKey(table, name, values, replaced) {
1524
+ const old = table.get(name);
1525
+ let changed = 0;
1526
+ if (old !== null) {
1527
+ for (let i = 0; i < values.length; i++) {
1528
+ const before = plainCell(old.value(i));
1529
+ const after = values[i] ?? null;
1530
+ if (before !== null && JSON.stringify(before) !== JSON.stringify(after)) {
1531
+ changed++;
1532
+ }
1533
+ }
1534
+ }
1535
+ if (changed > 0) {
1536
+ replaced.add(table === replaced.nodes ? "node" : "edge", name, changed);
1537
+ }
1538
+ if (values.every((v) => v === null || v === undefined)) {
1539
+ if (old !== null) {
1540
+ table.remove(name);
1541
+ }
1542
+ return;
1543
+ }
1544
+ setColumn(table, name, values);
1545
+ }
1546
+ /**
1547
+ * The code of the note that a data value held under a style key is replaced by what graphty draws.
1548
+ * @category Built-in formats
1549
+ */
1550
+ export const STYLE_KEY_REPLACED_CODE = "W_JSON_STYLE_KEY_REPLACED";
1551
+ /** Counts the data values a style key's picture replaces, per target and key. */
1552
+ class Replaced {
1553
+ /**
1554
+ * Counts the replaced values of one export.
1555
+ * @param nodes - the node table being written, which tells node columns from edge columns
1556
+ */
1557
+ constructor(nodes) {
1558
+ this.nodes = nodes;
1559
+ _Replaced_counts.set(this, new Map());
1560
+ }
1561
+ /**
1562
+ * Counts replaced values.
1563
+ * @param target - nodes or edges
1564
+ * @param key - the key
1565
+ * @param count - how many
1566
+ */
1567
+ add(target, key, count) {
1568
+ __classPrivateFieldGet(this, _Replaced_counts, "f").set(`${target}\u0000${key}`, (__classPrivateFieldGet(this, _Replaced_counts, "f").get(`${target}\u0000${key}`) ?? 0) + count);
1569
+ }
1570
+ /**
1571
+ * The notes, one per key.
1572
+ * @param dialect - the dialect, for the message
1573
+ * @returns the notes
1574
+ */
1575
+ notes(dialect) {
1576
+ return Array.from(__classPrivateFieldGet(this, _Replaced_counts, "f"), ([key, count]) => {
1577
+ const [target, name] = key.split("\u0000");
1578
+ return Object.freeze({
1579
+ code: STYLE_KEY_REPLACED_CODE,
1580
+ message: `${target} column "${name}" is the ${dialect} dialect's style key: ${String(count)} ${target}${count === 1 ? "" : "s"} get what graphty draws instead of the value the column held`,
1581
+ column: name,
1582
+ count,
1583
+ });
1584
+ });
1585
+ }
1586
+ }
1587
+ _Replaced_counts = new WeakMap();
1588
+ /**
1589
+ * A color with its alpha as CSS text: `#rrggbb`, or `rgba()` below full opacity.
1590
+ * @param color - the color
1591
+ * @param alpha - the opacity, or null
1592
+ * @returns the text, or null
1593
+ */
1594
+ function cssColor(color, alpha) {
1595
+ if (typeof color !== "string") {
1596
+ return null;
1597
+ }
1598
+ if (typeof alpha !== "number" || alpha >= 1) {
1599
+ return color;
1600
+ }
1601
+ const n = Number.parseInt(color.slice(1), 16);
1602
+ return `rgba(${String((n >> 16) & 255)},${String((n >> 8) & 255)},${String(n & 255)},${String(alpha)})`;
1603
+ }
1604
+ /**
1605
+ * One size for a node's width and height, noting a node whose two differ.
1606
+ * @param width - the widths
1607
+ * @param height - the heights
1608
+ * @param approximated - where approximations are counted
1609
+ * @returns the sizes
1610
+ */
1611
+ function nodeSizes(width, height, approximated) {
1612
+ return width.map((_v, i) => {
1613
+ const w = width[i];
1614
+ const h = height[i];
1615
+ if (typeof w === "number" && typeof h === "number" && w !== h) {
1616
+ approximated.add("node", w > h ? "height" : "width", `${String(w)} x ${String(h)}`);
1617
+ return Math.max(w, h);
1618
+ }
1619
+ if (typeof w === "number") {
1620
+ return w;
1621
+ }
1622
+ return typeof h === "number" ? h : null;
1623
+ });
1624
+ }
1625
+ /**
1626
+ * graphology: sigma.js's keys from the picture.
1627
+ * @param out - the graph being written
1628
+ * @param input - the styles
1629
+ * @param approximated - where approximations are counted
1630
+ * @param replaced - where replaced data values are counted
1631
+ */
1632
+ function writeGraphology(out, input, approximated, replaced) {
1633
+ const p = (target, property) => input.picture(target, property);
1634
+ for (const [table, target] of [
1635
+ [out.nodes, "node"],
1636
+ [out.edges, "edge"],
1637
+ ]) {
1638
+ const [fill, opacity] = target === "node" ? ["fill", "fillOpacity"] : ["color", "opacity"];
1639
+ const colors = p(target, fill);
1640
+ const alphas = p(target, opacity);
1641
+ writeKey(table, "color", colors.map((c, i) => cssColor(c, alphas[i])), replaced);
1642
+ writeKey(table, "size", target === "node" ? nodeSizes(p("node", "width"), p("node", "height"), approximated) : p("edge", "width"), replaced);
1643
+ writeKey(table, "label", p(target, "label"), replaced);
1644
+ writeKey(table, "hidden", p(target, "visible").map((v) => (v === false ? true : null)), replaced);
1645
+ }
1646
+ }
1647
+ /**
1648
+ * vis.js: vis-network's keys from the picture.
1649
+ * @param out - the graph being written
1650
+ * @param input - the styles
1651
+ * @param approximated - where approximations are counted
1652
+ * @param replaced - where replaced data values are counted
1653
+ */
1654
+ function writeVis(out, input, approximated, replaced) {
1655
+ const p = (target, property) => input.picture(target, property);
1656
+ const font = (target) => {
1657
+ const color = p(target, "labelColor");
1658
+ const size = p(target, "labelSize");
1659
+ const face = p(target, "labelFont");
1660
+ return color.map((_v, i) => {
1661
+ const f = {};
1662
+ if (color[i] !== null) {
1663
+ f.color = color[i];
1664
+ }
1665
+ if (size[i] !== null) {
1666
+ f.size = size[i];
1667
+ }
1668
+ if (face[i] !== null) {
1669
+ f.face = face[i];
1670
+ }
1671
+ return Object.keys(f).length === 0 ? null : f;
1672
+ });
1673
+ };
1674
+ const label = (table, target) => {
1675
+ writeKey(table, "label", p(target, "label"), replaced);
1676
+ writeKey(table, "title", p(target, "tooltip"), replaced);
1677
+ writeKey(table, "font", font(target), replaced);
1678
+ writeKey(table, "hidden", p(target, "visible").map((v) => (v === false ? true : null)), replaced);
1679
+ };
1680
+ const fill = p("node", "fill");
1681
+ const fillOpacity = p("node", "fillOpacity");
1682
+ const border = p("node", "borderColor");
1683
+ writeKey(out.nodes, "color", fill.map((_v, i) => {
1684
+ const c = {};
1685
+ const bg = cssColor(fill[i], fillOpacity[i]);
1686
+ if (bg !== null) {
1687
+ c.background = bg;
1688
+ }
1689
+ if (typeof border[i] === "string") {
1690
+ c.border = border[i];
1691
+ }
1692
+ return Object.keys(c).length === 0 ? null : c;
1693
+ }), replaced);
1694
+ const sizes = nodeSizes(p("node", "width"), p("node", "height"), approximated);
1695
+ const shapes = p("node", "shape").map((s, i) => {
1696
+ const [shape, exact] = typeof s === "string" ? visShape(s) : [null, true];
1697
+ if (!exact) {
1698
+ approximated.add("node", "shape", s);
1699
+ }
1700
+ if (sizes[i] !== null && !VIS_SIZED.has(shape ?? "ellipse")) {
1701
+ approximated.add("node", "width", `${String(s ?? "ellipse")} sized by its label`);
1702
+ }
1703
+ return shape;
1704
+ });
1705
+ writeKey(out.nodes, "shape", shapes, replaced);
1706
+ writeKey(out.nodes, "size", sizes, replaced);
1707
+ writeKey(out.nodes, "borderWidth", p("node", "borderWidth"), replaced);
1708
+ writeKey(out.nodes, "opacity", p("node", "opacity"), replaced);
1709
+ label(out.nodes, "node");
1710
+ const color = p("edge", "color");
1711
+ const opacity = p("edge", "opacity");
1712
+ writeKey(out.edges, "color", color.map((_v, e) => {
1713
+ const c = {};
1714
+ if (typeof color[e] === "string") {
1715
+ c.color = color[e];
1716
+ }
1717
+ if (typeof opacity[e] === "number") {
1718
+ c.opacity = opacity[e];
1719
+ }
1720
+ return Object.keys(c).length === 0 ? null : c;
1721
+ }), replaced);
1722
+ writeKey(out.edges, "width", p("edge", "width"), replaced);
1723
+ writeKey(out.edges, "dashes", p("edge", "lineStyle").map((s) => {
1724
+ if (typeof s !== "string") {
1725
+ return null;
1726
+ }
1727
+ if (s !== "solid" && s !== "dashed") {
1728
+ approximated.add("edge", "lineStyle", s);
1729
+ }
1730
+ return s !== "solid";
1731
+ }), replaced);
1732
+ const to = p("edge", "targetArrow");
1733
+ const from = p("edge", "sourceArrow");
1734
+ writeKey(out.edges, "arrows", to.map((_v, e) => {
1735
+ const a = {};
1736
+ for (const [end, value, property] of [
1737
+ ["to", to[e], "targetArrow"],
1738
+ ["from", from[e], "sourceArrow"],
1739
+ ]) {
1740
+ if (typeof value !== "string") {
1741
+ continue;
1742
+ }
1743
+ const [type, exact] = visArrowType(value);
1744
+ if (!exact) {
1745
+ approximated.add("edge", property, value);
1746
+ }
1747
+ a[end] = type === null ? { enabled: false } : { enabled: true, type };
1748
+ }
1749
+ return Object.keys(a).length === 0 ? null : a;
1750
+ }), replaced);
1751
+ label(out.edges, "edge");
1752
+ }
1753
+ //# sourceMappingURL=styles.js.map