@graphty/graph-io 0.3.43 → 0.3.44

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-3Q4TsdTh.js +40 -0
  2. package/dist/chunks/approximations-3Q4TsdTh.js.map +1 -0
  3. package/dist/chunks/block-JQiwViEt.js +2777 -0
  4. package/dist/chunks/block-JQiwViEt.js.map +1 -0
  5. package/dist/chunks/{choose-DvpbdRuz.js → choose-BemygfH8.js} +3 -2
  6. package/dist/chunks/{choose-DvpbdRuz.js.map → choose-BemygfH8.js.map} +1 -1
  7. package/dist/chunks/{constants-fT3E8JYY.js → constants-BFUR_CtU.js} +6 -2
  8. package/dist/chunks/constants-BFUR_CtU.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-DCwFLts5.js +3456 -0
  12. package/dist/chunks/emit-DCwFLts5.js.map +1 -0
  13. package/dist/chunks/{escape-B62ZGM_a.js → escape-B1rMftd9.js} +43 -20
  14. package/dist/chunks/escape-B1rMftd9.js.map +1 -0
  15. package/dist/chunks/{export-rKLeGQMo.js → export-D7IGzTG4.js} +196 -792
  16. package/dist/chunks/export-D7IGzTG4.js.map +1 -0
  17. package/dist/chunks/{exporter-BWwEuOPT.js → exporter-BtnqYuuj.js} +22 -12
  18. package/dist/chunks/exporter-BtnqYuuj.js.map +1 -0
  19. package/dist/chunks/{exporter-yLxKBvLE.js → exporter-ChPyhBOv.js} +4 -3
  20. package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter-ChPyhBOv.js.map} +1 -1
  21. package/dist/chunks/{exporter-8hLNemFk.js → exporter-KEPxYUXD.js} +133 -74
  22. package/dist/chunks/exporter-KEPxYUXD.js.map +1 -0
  23. package/dist/chunks/{exporter-RVtXVetw.js → exporter-quPUCBiC.js} +1805 -287
  24. package/dist/chunks/exporter-quPUCBiC.js.map +1 -0
  25. package/dist/chunks/format-GDmO6m6Q.js +676 -0
  26. package/dist/chunks/format-GDmO6m6Q.js.map +1 -0
  27. package/dist/chunks/generic-BL06jrJf.js +1347 -0
  28. package/dist/chunks/generic-BL06jrJf.js.map +1 -0
  29. package/dist/chunks/{importer-WrGRZb0N.js → importer-B7r2owVf.js} +449 -102
  30. package/dist/chunks/importer-B7r2owVf.js.map +1 -0
  31. package/dist/chunks/{importer-Ht7LNg8L.js → importer-BFmOP96W.js} +116 -296
  32. package/dist/chunks/importer-BFmOP96W.js.map +1 -0
  33. package/dist/chunks/{importer-BbNb7eNg.js → importer-C2nzGhdV.js} +1390 -129
  34. package/dist/chunks/importer-C2nzGhdV.js.map +1 -0
  35. package/dist/chunks/{importer-Dz7tI8Sa.js → importer-CbX2_rNF.js} +617 -115
  36. package/dist/chunks/importer-CbX2_rNF.js.map +1 -0
  37. package/dist/chunks/{importer-D794XUTe.js → importer-CdzeN6X4.js} +31 -8
  38. package/dist/chunks/importer-CdzeN6X4.js.map +1 -0
  39. package/dist/chunks/{importer-xZ-3suY1.js → importer-ChKNC_GN.js} +791 -135
  40. package/dist/chunks/importer-ChKNC_GN.js.map +1 -0
  41. package/dist/chunks/{importer-C98dpSH4.js → importer-dwoYpSqb.js} +141 -82
  42. package/dist/chunks/importer-dwoYpSqb.js.map +1 -0
  43. package/dist/chunks/index-B9fdNpTA.js +4310 -0
  44. package/dist/chunks/index-B9fdNpTA.js.map +1 -0
  45. package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-C4FwgnH5.js} +123 -32
  46. package/dist/chunks/json-elements-C4FwgnH5.js.map +1 -0
  47. package/dist/chunks/lexicon-B-knUi-l.js +508 -0
  48. package/dist/chunks/lexicon-B-knUi-l.js.map +1 -0
  49. package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-BSpbY5FL.js} +3 -2
  50. package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-BSpbY5FL.js.map} +1 -1
  51. package/dist/chunks/{records-Cu4bxYOm.js → records-Nwz_rbNt.js} +2 -2
  52. package/dist/chunks/{records-Cu4bxYOm.js.map → records-Nwz_rbNt.js.map} +1 -1
  53. package/dist/chunks/styles-Brt9JMfs.js +690 -0
  54. package/dist/chunks/styles-Brt9JMfs.js.map +1 -0
  55. package/dist/chunks/styles-_N-C8S-U.js +2102 -0
  56. package/dist/chunks/styles-_N-C8S-U.js.map +1 -0
  57. package/dist/chunks/styles-yed-DAfcIkf7.js +842 -0
  58. package/dist/chunks/styles-yed-DAfcIkf7.js.map +1 -0
  59. package/dist/chunks/{text-DHOJXnED.js → text-CgzMqHQb.js} +2 -2
  60. package/dist/chunks/{text-DHOJXnED.js.map → text-CgzMqHQb.js.map} +1 -1
  61. package/dist/chunks/units-XMZFIFe1.js +19 -0
  62. package/dist/chunks/units-XMZFIFe1.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 +8 -3031
  73. package/dist/gml.js.map +1 -1
  74. package/dist/graph-io.js +354 -240
  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 +1484 -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 +790 -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 +603 -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 +80 -0
  489. package/dist/src/styles/io/writer.d.ts.map +1 -0
  490. package/dist/src/styles/io/writer.js +596 -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 +1741 -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 +951 -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 +656 -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 +745 -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,930 @@
1
+ /**
2
+ * The `graphty.styles` block: the rules of a graph's styles written into a file so that importing the file back into
3
+ * graphty rebuilds the same rules. The block is JSON; the per-element values its rules read are written beside it as
4
+ * element attributes named `graphty.style.<target>.<key>` (or, in a format with no per-element attributes, inside
5
+ * the block). A block is file input like any other: it is size-limited, validated member by member, never keyed into
6
+ * a plain object, and a block that fails any check is ignored with a reason code, never thrown.
7
+ */
8
+ import { STYLE_ISSUE } from "../codes.js";
9
+ import { toolDefaults } from "../defaults.js";
10
+ import { featuresOf, heldEdgeRows, styleFingerprint } from "../plan/features.js";
11
+ import { plainCell, refSource, resolveRules, within } from "../plan/resolve.js";
12
+ import { STYLE_PROPERTIES } from "../vocabulary.js";
13
+ /**
14
+ * The name of the block in every format: a graph attribute, a key, an aspect or an archive entry.
15
+ * @category Styles
16
+ */
17
+ export const STYLE_BLOCK_NAME = "graphty.styles";
18
+ /**
19
+ * The longest block graph-io reads, in characters; a longer one is ignored (`TOO_LARGE`).
20
+ * @category Styles
21
+ */
22
+ export const MAX_STYLE_BLOCK_LENGTH = 16 * 1024 * 1024;
23
+ /** The deepest nesting of JSON values a block may have. */
24
+ const MAX_DEPTH = 64;
25
+ /** The most rules a block may hold. */
26
+ const MAX_RULES = 4096;
27
+ /** The longest id, key, property name or source field. */
28
+ const MAX_NAME = 256;
29
+ /** Keys that would reach an object's prototype; a block holding one anywhere is ignored. */
30
+ const FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
31
+ const TARGETS = ["node", "edge"];
32
+ const COMPUTED = new Set(["degree", "indegree", "outdegree"]);
33
+ /**
34
+ * The name of the element attribute holding one style column: `graphty.style.<target>.<key>`.
35
+ * @param target - nodes or edges
36
+ * @param key - the style column's key (`class`, `member.3`, `exceptions.fill`)
37
+ * @returns the attribute name
38
+ * @category Styles
39
+ */
40
+ export function styleTag(target, key) {
41
+ return `graphty.style.${target}.${key}`;
42
+ }
43
+ /** The JSON escapes a reader of Cytoscape's convention would change, as `\u` escapes that mean the same. */
44
+ const SAFE_ESCAPES = {
45
+ "\\": String.raw `\u005c`,
46
+ n: String.raw `\u000a`,
47
+ t: String.raw `\u0009`,
48
+ };
49
+ /**
50
+ * Writes a graph's styles as a `graphty.styles` block. Notes are not written. The output is deterministic: the same
51
+ * styles always give the same text. A backslash, newline or tab inside a string is written as a `\u` escape, so a
52
+ * format that decodes `\n` and `\t` in attribute values (Cytoscape's convention) reads the block back unchanged.
53
+ * @param extracted - the styles
54
+ * @param options - whether to write the style columns inside the block
55
+ * @returns the block's JSON text
56
+ * @category Styles
57
+ */
58
+ export function writeStyleBlock(extracted, options = {}) {
59
+ const { styles, columns, fingerprint } = extracted;
60
+ const out = {
61
+ version: 1,
62
+ source: styles.source,
63
+ units: styles.units,
64
+ graph: styles.graph,
65
+ rules: styles.rules,
66
+ columns: { node: Array.from(columns.node.keys()), edge: Array.from(columns.edge.keys()) },
67
+ };
68
+ const booleanKeys = (byKey) => Array.from(byKey)
69
+ .filter(([, col]) => col.some((x) => x !== null) && col.every((x) => x === null || typeof x === "boolean"))
70
+ .map(([key]) => key);
71
+ const booleans = { node: booleanKeys(columns.node), edge: booleanKeys(columns.edge) };
72
+ if (booleans.node.length > 0 || booleans.edge.length > 0) {
73
+ out.booleans = booleans;
74
+ }
75
+ if (options.inlineColumns === true) {
76
+ if (options.snapshot !== undefined) {
77
+ const { ids, nodeCount } = options.snapshot;
78
+ out.order = Array.from({ length: nodeCount }, (_unused, i) => String(ids.idOf(i)));
79
+ }
80
+ // an edge's values are listed once per edge the file holds
81
+ const held = options.snapshot === undefined ? null : heldEdgeRows(options.snapshot);
82
+ out.values = {
83
+ node: Object.fromEntries(columns.node),
84
+ edge: Object.fromEntries(Array.from(columns.edge, ([key, col]) => [key, held === null ? col : held.map((e) => col[e] ?? null)])),
85
+ };
86
+ }
87
+ const { snapshot } = options;
88
+ if (snapshot !== undefined) {
89
+ const hashes = (target) => {
90
+ const table = target === "node" ? snapshot.nodes : snapshot.edges;
91
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
92
+ // a name the reader refuses as a key is left out: its rules then find the column by its name alone
93
+ const read = dataNames(styles.rules.filter((r) => r.target === target))
94
+ .filter((c) => table.has(c) && !FORBIDDEN_KEYS.has(c) && c.length <= MAX_NAME)
95
+ .slice(0, MAX_RULES);
96
+ return Object.fromEntries(read.map((c) => [c, columnHash(table, c, n)]));
97
+ };
98
+ out.data = { node: hashes("node"), edge: hashes("edge") };
99
+ }
100
+ out.fingerprint = {
101
+ nodes: fingerprint.nodes,
102
+ edges: fingerprint.heldEdges ?? fingerprint.edges,
103
+ ids: fingerprint.ids,
104
+ };
105
+ return JSON.stringify(out).replaceAll(/\\(.)/g, (escape, c) => SAFE_ESCAPES[c] ?? escape);
106
+ }
107
+ /**
108
+ * The loss when graph-io would ignore a block it has just written: one longer than `MAX_STYLE_BLOCK_LENGTH`, or one
109
+ * past another limit the reader enforces (too many rules, a name too long). The format's own styles are still
110
+ * written, so importing the file back infers the rules again from them.
111
+ * @param text - the block's text, as `writeStyleBlock()` wrote it
112
+ * @param rules - how many rules the block holds
113
+ * @param check - "size" to check only the length: a block rewritten with its columns inline, whose rules were
114
+ * checked already
115
+ * @returns one `W_STYLE_RULES_NOT_KEPT` note naming the reason, or none when the block reads back
116
+ * @category Styles
117
+ */
118
+ export function styleBlockLosses(text, rules, check = "all") {
119
+ let reason = null;
120
+ if (text.length > MAX_STYLE_BLOCK_LENGTH) {
121
+ reason = "TOO_LARGE";
122
+ }
123
+ else if (check === "all") {
124
+ const top = JSON.parse(text);
125
+ const { nodes, edges, ids } = top.fingerprint;
126
+ const parsed = parseStyleBlock(text, { nodes, edges, ids });
127
+ reason = parsed.ok ? null : parsed.reason;
128
+ }
129
+ if (reason === null) {
130
+ return [];
131
+ }
132
+ return [
133
+ Object.freeze({
134
+ code: STYLE_ISSUE.RULES_NOT_KEPT,
135
+ message: `the ${STYLE_BLOCK_NAME} block would not read back (${reason}): the styles are written as the format's own, and importing the file infers the rules again`,
136
+ column: null,
137
+ count: rules,
138
+ }),
139
+ ];
140
+ }
141
+ /** Thrown inside the validator only; turned into an `INVALID` result before parseStyleBlock() returns. */
142
+ class Invalid extends Error {
143
+ }
144
+ /**
145
+ * Fails validation: throws `Invalid`, which parseStyleBlock() turns into an `INVALID` result.
146
+ * @throws Invalid always
147
+ */
148
+ function invalid() {
149
+ throw new Invalid();
150
+ }
151
+ /**
152
+ * Reads a `graphty.styles` block as untrusted input. It never throws: a block that is not text, too large, not JSON,
153
+ * of another version, nested too deep, holding a key that reaches a prototype (`__proto__`), shaped wrongly or
154
+ * written for a different graph is ignored with the reason.
155
+ * @param text - the block's text, as the file holds it
156
+ * @param fingerprint - the graph being imported (`styleFingerprint(snapshot)`)
157
+ * @returns the block, or why it is ignored
158
+ * @category Styles
159
+ */
160
+ export function parseStyleBlock(text, fingerprint) {
161
+ if (typeof text !== "string") {
162
+ return { ok: false, reason: "INVALID" };
163
+ }
164
+ if (text.length > MAX_STYLE_BLOCK_LENGTH) {
165
+ return { ok: false, reason: "TOO_LARGE" };
166
+ }
167
+ let json;
168
+ try {
169
+ json = JSON.parse(text);
170
+ }
171
+ catch {
172
+ return { ok: false, reason: "NOT_JSON" };
173
+ }
174
+ if (!safeTree(json)) {
175
+ return { ok: false, reason: "INVALID" };
176
+ }
177
+ const top = isObject(json) ? json : null;
178
+ if (top === null) {
179
+ return { ok: false, reason: "INVALID" };
180
+ }
181
+ if (top.version !== 1) {
182
+ return { ok: false, reason: "VERSION" };
183
+ }
184
+ // a block for another graph says so, whatever else in it would not fit this one
185
+ const fp = isObject(top.fingerprint) ? top.fingerprint : null;
186
+ if (fp !== null &&
187
+ (fp.nodes !== fingerprint.nodes ||
188
+ fp.edges !== (fingerprint.heldEdges ?? fingerprint.edges) ||
189
+ fp.ids !== fingerprint.ids)) {
190
+ return { ok: false, reason: "FINGERPRINT" };
191
+ }
192
+ let block;
193
+ try {
194
+ block = readBlock(top);
195
+ }
196
+ catch (err) {
197
+ if (err instanceof Invalid) {
198
+ return { ok: false, reason: "INVALID" };
199
+ }
200
+ throw err;
201
+ }
202
+ const f = block.fingerprint;
203
+ if (f.nodes !== fingerprint.nodes ||
204
+ f.edges !== (fingerprint.heldEdges ?? fingerprint.edges) ||
205
+ f.ids !== fingerprint.ids) {
206
+ return { ok: false, reason: "FINGERPRINT" };
207
+ }
208
+ return { ok: true, block };
209
+ }
210
+ /**
211
+ * Whether a parsed JSON value is at most `MAX_DEPTH` deep and holds no key that reaches a prototype. Walked with an
212
+ * explicit stack, never by recursion.
213
+ * @param root - the parsed value
214
+ * @returns true when safe
215
+ */
216
+ function safeTree(root) {
217
+ const stack = [[root, 0]];
218
+ while (stack.length > 0) {
219
+ const [v, depth] = stack.pop();
220
+ if (v === null || typeof v !== "object") {
221
+ continue;
222
+ }
223
+ if (depth >= MAX_DEPTH || (!Array.isArray(v) && Object.keys(v).some((key) => FORBIDDEN_KEYS.has(key)))) {
224
+ return false;
225
+ }
226
+ const items = Array.isArray(v) ? v : Object.values(v);
227
+ for (const item of items) {
228
+ if (item !== null && typeof item === "object") {
229
+ stack.push([item, depth + 1]);
230
+ }
231
+ }
232
+ }
233
+ return true;
234
+ }
235
+ /**
236
+ * Whether a value is a plain JSON object (not an array, not null).
237
+ * @param v - the value
238
+ * @returns true for an object
239
+ */
240
+ function isObject(v) {
241
+ return v !== null && typeof v === "object" && !Array.isArray(v);
242
+ }
243
+ /**
244
+ * A short string, or invalid.
245
+ * @param v - the value
246
+ * @returns the string
247
+ */
248
+ function name(v) {
249
+ return typeof v === "string" && v.length <= MAX_NAME ? v : invalid();
250
+ }
251
+ /**
252
+ * A short string or null, or invalid.
253
+ * @param v - the value
254
+ * @returns the string or null
255
+ */
256
+ function nameOrNull(v) {
257
+ return v === null || v === undefined ? null : name(v);
258
+ }
259
+ /**
260
+ * Whether a value is a scalar: a string, a finite number or a boolean.
261
+ * @param v - the value
262
+ * @returns true for a scalar
263
+ */
264
+ function isScalar(v) {
265
+ return typeof v === "string" || typeof v === "boolean" || (typeof v === "number" && Number.isFinite(v));
266
+ }
267
+ /**
268
+ * A scalar, or invalid.
269
+ * @param v - the value
270
+ * @returns the scalar
271
+ */
272
+ function scalar(v) {
273
+ return isScalar(v) ? v : invalid();
274
+ }
275
+ /**
276
+ * An array, or invalid.
277
+ * @param v - the value
278
+ * @param max - the most items allowed
279
+ * @returns the array
280
+ */
281
+ function array(v, max) {
282
+ return Array.isArray(v) && v.length <= max ? v : invalid();
283
+ }
284
+ /**
285
+ * The whole block.
286
+ * @param top - the parsed object
287
+ * @returns the block
288
+ */
289
+ function readBlock(top) {
290
+ const source = isObject(top.source) ? top.source : invalid();
291
+ const units = isObject(top.units) ? top.units : invalid();
292
+ const length = units.length === "px" || units.length === "relative" ? units.length : invalid();
293
+ const fp = isObject(top.fingerprint) ? top.fingerprint : invalid();
294
+ const count = (v) => (typeof v === "number" && Number.isSafeInteger(v) && v >= 0 ? v : invalid());
295
+ const cols = isObject(top.columns) ? top.columns : invalid();
296
+ const block = {
297
+ version: 1,
298
+ source: { format: name(source.format), dialect: nameOrNull(source.dialect), tool: nameOrNull(source.tool) },
299
+ units: { length },
300
+ graph: values(top.graph ?? {}),
301
+ rules: array(top.rules, MAX_RULES).map(readRule),
302
+ columns: {
303
+ node: array(cols.node, MAX_RULES).map(name),
304
+ edge: array(cols.edge, MAX_RULES).map(name),
305
+ },
306
+ fingerprint: { nodes: count(fp.nodes), edges: count(fp.edges), ids: name(fp.ids) },
307
+ };
308
+ const read = top.data === undefined ? block : { ...block, data: readData(top.data) };
309
+ const withData = top.booleans === undefined ? read : { ...read, booleans: readBooleans(top.booleans) };
310
+ if (top.values === undefined) {
311
+ return withData;
312
+ }
313
+ const order = top.order === undefined ? undefined : readOrder(top.order, block.fingerprint.nodes);
314
+ const inline = readInline(top.values, block);
315
+ return { ...withData, ...(order === undefined ? {} : { order }), values: inline };
316
+ }
317
+ /**
318
+ * The boolean style columns of a block, by target.
319
+ * @param v - the parsed `booleans` member
320
+ * @returns the column keys
321
+ */
322
+ function readBooleans(v) {
323
+ const booleans = isObject(v) ? v : invalid();
324
+ return {
325
+ node: array(booleans.node ?? [], MAX_RULES).map(name),
326
+ edge: array(booleans.edge ?? [], MAX_RULES).map(name),
327
+ };
328
+ }
329
+ /**
330
+ * The node ids of a block, in the order its inline values list the nodes.
331
+ * @param v - the parsed `order` member
332
+ * @param nodes - the node count of its fingerprint
333
+ * @returns the ids
334
+ */
335
+ function readOrder(v, nodes) {
336
+ const order = array(v, nodes).map((id) => (typeof id === "string" ? id : invalid()));
337
+ return order.length === nodes ? order : invalid();
338
+ }
339
+ /**
340
+ * The style columns written inside a block: one value per node or edge for each column the block names.
341
+ * @param v - the parsed `values` member
342
+ * @param block - the block read so far
343
+ * @returns the columns, by target
344
+ */
345
+ function readInline(v, block) {
346
+ const values = isObject(v) ? v : invalid();
347
+ const inline = { node: new Map(), edge: new Map() };
348
+ for (const target of TARGETS) {
349
+ const n = target === "node" ? block.fingerprint.nodes : block.fingerprint.edges;
350
+ const byKey = isObject(values[target]) ? values[target] : invalid();
351
+ for (const key of block.columns[target]) {
352
+ const col = array(Object.hasOwn(byKey, key) ? byKey[key] : invalid(), n);
353
+ if (col.length !== n) {
354
+ invalid();
355
+ }
356
+ inline[target].set(key, col.map((x) => (x === null ? null : scalar(x))));
357
+ }
358
+ }
359
+ return inline;
360
+ }
361
+ /**
362
+ * The data column hashes of a block.
363
+ * @param v - the parsed `data` member
364
+ * @returns the hashes by column name, per target
365
+ */
366
+ function readData(v) {
367
+ const d = isObject(v) ? v : invalid();
368
+ const byTarget = (t) => {
369
+ const o = isObject(t) ? t : invalid();
370
+ const keys = Object.keys(o);
371
+ if (keys.length > MAX_RULES) {
372
+ invalid();
373
+ }
374
+ return new Map(keys.map((k) => [name(k), name(o[k])]));
375
+ };
376
+ return { node: byTarget(d.node), edge: byTarget(d.edge) };
377
+ }
378
+ /**
379
+ * A cell's value as text: a list as JSON, no value as a character no text holds.
380
+ * @param v - the cell
381
+ * @returns the text
382
+ */
383
+ function cellText(v) {
384
+ if (v === null) {
385
+ return "\u0001";
386
+ }
387
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
388
+ return String(v);
389
+ }
390
+ return JSON.stringify(v);
391
+ }
392
+ /**
393
+ * A hash of a column's values as text, by element index: the text of a value, so a format that reads the number 7
394
+ * back as "7" keeps the hash.
395
+ * @param table - the node or edge table
396
+ * @param column - the column's name
397
+ * @param n - the element count
398
+ * @returns the hash
399
+ */
400
+ function columnHash(table, column, n) {
401
+ let h1 = 0x811c9dc5;
402
+ let h2 = 0x01000193 ^ 0x5bd1e995;
403
+ for (let i = 0; i < n; i++) {
404
+ const text = `${cellText(plainCell(table.value(column, i)))}\u0000`;
405
+ for (let c = 0; c < text.length; c++) {
406
+ const code = text.charCodeAt(c); // NOSONAR(S7758): hashes UTF-16 code units; code points would change every written hash
407
+ h1 = Math.imul(h1 ^ code, 0x01000193);
408
+ h2 = Math.imul(h2 ^ code, 0x01000193) ^ (h2 >>> 13);
409
+ }
410
+ }
411
+ const hex = (h) => (h >>> 0).toString(16).padStart(8, "0");
412
+ return hex(h1) + hex(h2);
413
+ }
414
+ /**
415
+ * Every data column some rule reads, in first-read order. A rule's `ext` is the consumer's own and is not read.
416
+ * @param rules - the rules
417
+ * @returns the column names
418
+ */
419
+ function dataNames(rules) {
420
+ const out = new Set();
421
+ for (const { ext: _ext, ...rule } of rules) {
422
+ JSON.stringify(rule, (_k, v) => {
423
+ if (isObject(v) && typeof v.data === "string" && Object.keys(v).length === 1) {
424
+ out.add(v.data);
425
+ }
426
+ return v;
427
+ });
428
+ }
429
+ return [...out];
430
+ }
431
+ /**
432
+ * A rule with its data column references renamed; its `ext` is kept untouched.
433
+ * @param rule - the rule
434
+ * @param rename - the new name of each column that moved
435
+ * @returns the rule
436
+ */
437
+ function renameData(rule, rename) {
438
+ const { ext, ...rest } = rule;
439
+ const moved = JSON.parse(JSON.stringify(rest, (_k, v) => isObject(v) && typeof v.data === "string" && Object.keys(v).length === 1 && rename.has(v.data)
440
+ ? { data: rename.get(v.data) }
441
+ : v));
442
+ return ext === undefined ? moved : { ...moved, ext };
443
+ }
444
+ /**
445
+ * Where each data column a block's rules read is in the imported graph: under its own name when its values are the
446
+ * same, else the first column holding the same values (a format that renamed it), else under its own name.
447
+ * @param block - the block
448
+ * @param snapshot - the graph
449
+ * @param target - nodes or edges
450
+ * @returns the new name of each column that moved
451
+ */
452
+ function movedColumns(block, snapshot, target) {
453
+ const moved = new Map();
454
+ const want = block.data?.[target];
455
+ if (want === undefined || want.size === 0) {
456
+ return moved;
457
+ }
458
+ const table = target === "node" ? snapshot.nodes : snapshot.edges;
459
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
460
+ let have = null;
461
+ for (const [column, hash] of want) {
462
+ if (table.has(column) && columnHash(table, column, n) === hash) {
463
+ continue;
464
+ }
465
+ have ?? (have = new Map(Array.from(table.names(), (c) => [c, columnHash(table, c, n)])));
466
+ for (const [c, h] of have) {
467
+ if (h === hash) {
468
+ moved.set(column, c);
469
+ break;
470
+ }
471
+ }
472
+ }
473
+ return moved;
474
+ }
475
+ /**
476
+ * A record of style values, copied into a null-prototype object.
477
+ * @param v - the parsed record
478
+ * @returns the copy
479
+ */
480
+ function values(v) {
481
+ const o = isObject(v) ? v : invalid();
482
+ const out = Object.create(null);
483
+ for (const key of Object.keys(o)) {
484
+ out[name(key)] = scalar(o[key]);
485
+ }
486
+ return out;
487
+ }
488
+ /**
489
+ * One rule.
490
+ * @param v - the parsed rule
491
+ * @returns the rule
492
+ */
493
+ function readRule(v) {
494
+ const r = isObject(v) ? v : invalid();
495
+ const target = r.target === "node" || r.target === "edge" ? r.target : invalid();
496
+ const rule = {
497
+ id: name(r.id),
498
+ target,
499
+ role: name(r.role),
500
+ origin: name(r.origin),
501
+ where: predicate(r.where),
502
+ };
503
+ if (r.set !== undefined) {
504
+ rule.set = values(r.set);
505
+ }
506
+ if (r.map !== undefined) {
507
+ const m = isObject(r.map) ? r.map : invalid();
508
+ const map = Object.create(null);
509
+ for (const key of Object.keys(m)) {
510
+ map[name(key)] = mapping(m[key]);
511
+ }
512
+ rule.map = map;
513
+ }
514
+ if (r.facts !== undefined) {
515
+ rule.facts = facts(r.facts);
516
+ }
517
+ if (r.ext !== undefined) {
518
+ // carried untouched for the consumer that wrote it; safeTree() already checked its keys and depth
519
+ rule.ext = isObject(r.ext) ? r.ext : invalid();
520
+ }
521
+ return rule;
522
+ }
523
+ /**
524
+ * A column reference.
525
+ * @param v - the parsed reference
526
+ * @returns the reference
527
+ */
528
+ function columnRef(v) {
529
+ const o = isObject(v) ? v : invalid();
530
+ if (typeof o.data === "string") {
531
+ return { data: name(o.data) };
532
+ }
533
+ if (typeof o.style === "string") {
534
+ return { style: name(o.style) };
535
+ }
536
+ if (typeof o.computed === "string" && COMPUTED.has(o.computed)) {
537
+ return { computed: o.computed };
538
+ }
539
+ return invalid();
540
+ }
541
+ /**
542
+ * A predicate. A predicate of a kind this version does not know is kept as it is and matches nothing.
543
+ * @param v - the parsed predicate
544
+ * @returns the predicate
545
+ */
546
+ function predicate(v) {
547
+ const o = isObject(v) ? v : invalid();
548
+ if ("all" in o) {
549
+ return o.all === true ? { all: true } : invalid();
550
+ }
551
+ if ("has" in o) {
552
+ return { has: columnRef(o.has) };
553
+ }
554
+ if ("eq" in o) {
555
+ const t = array(o.eq, 2);
556
+ return t.length === 2 ? { eq: [columnRef(t[0]), scalar(t[1])] } : invalid();
557
+ }
558
+ if ("in" in o) {
559
+ const t = array(o.in, 2);
560
+ return t.length === 2 ? { in: [columnRef(t[0]), array(t[1], 65536).map(scalar)] } : invalid();
561
+ }
562
+ if ("and" in o) {
563
+ return { and: array(o.and, 64).map(predicate) };
564
+ }
565
+ if ("or" in o) {
566
+ return { or: array(o.or, 64).map(predicate) };
567
+ }
568
+ if ("not" in o) {
569
+ return { not: predicate(o.not) };
570
+ }
571
+ return o;
572
+ }
573
+ /**
574
+ * A mapping. A mapping of a kind this version does not know is kept and gives no value.
575
+ * @param v - the parsed mapping
576
+ * @returns the mapping
577
+ */
578
+ function mapping(v) {
579
+ const o = isObject(v) ? v : invalid();
580
+ const by = columnRef(o.by);
581
+ switch (o.kind) {
582
+ case "passthrough":
583
+ return { kind: "passthrough", by };
584
+ case "discrete":
585
+ return {
586
+ kind: "discrete",
587
+ by,
588
+ table: array(o.table, 1 << 20).map((pair) => {
589
+ const p = array(pair, 2);
590
+ return p.length === 2 ? [scalar(p[0]), scalar(p[1])] : invalid();
591
+ }),
592
+ };
593
+ case "continuous":
594
+ return {
595
+ kind: "continuous",
596
+ by,
597
+ points: array(o.points, 4096).map((pt) => {
598
+ const q = isObject(pt) ? pt : invalid();
599
+ return {
600
+ at: typeof q.at === "number" && Number.isFinite(q.at) ? q.at : invalid(),
601
+ below: scalar(q.below),
602
+ value: scalar(q.value),
603
+ above: scalar(q.above),
604
+ };
605
+ }),
606
+ };
607
+ default:
608
+ return { ...o, kind: name(o.kind), by };
609
+ }
610
+ }
611
+ /**
612
+ * A rule's facts: the known members, each checked; anything else is left out.
613
+ * @param v - the parsed facts
614
+ * @returns the facts
615
+ */
616
+ function facts(v) {
617
+ const o = isObject(v) ? v : invalid();
618
+ const count = (x) => typeof x === "number" && Number.isSafeInteger(x) && x >= 0 ? x : undefined;
619
+ const out = {};
620
+ const elements = count(o.elements);
621
+ const classes = count(o.classes);
622
+ const distinctValues = count(o.distinctValues);
623
+ if (elements !== undefined) {
624
+ out.elements = elements;
625
+ }
626
+ if (classes !== undefined) {
627
+ out.classes = classes;
628
+ }
629
+ if (distinctValues !== undefined) {
630
+ out.distinctValues = distinctValues;
631
+ }
632
+ if (typeof o.reason === "string") {
633
+ out.reason = name(o.reason);
634
+ }
635
+ if (o.names !== undefined) {
636
+ out.names = array(o.names, 1 << 20).map((pair) => {
637
+ const p = array(pair, 2);
638
+ return p.length === 2 ? [scalar(p[0]), String(scalar(p[1]))] : invalid();
639
+ });
640
+ }
641
+ return out;
642
+ }
643
+ /**
644
+ * The style columns a block's rules read, from the block itself or from the tagged element attributes of the
645
+ * snapshot; null when one is missing.
646
+ * @param block - the block
647
+ * @param snapshot - the graph
648
+ * @param target - nodes or edges
649
+ * @returns the columns by key, or null
650
+ */
651
+ function blockColumns(block, snapshot, target) {
652
+ const out = new Map();
653
+ const table = target === "node" ? snapshot.nodes : snapshot.edges;
654
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
655
+ for (const key of block.columns[target]) {
656
+ const inline = block.values?.[target].get(key);
657
+ if (inline !== undefined) {
658
+ out.set(key, target === "node" ? inNodeOrder(block, snapshot, inline) : onEdgeRows(snapshot, inline));
659
+ continue;
660
+ }
661
+ const tag = styleTag(target, key);
662
+ if (!table.has(tag)) {
663
+ return null;
664
+ }
665
+ const col = Array.from({ length: n }, (_, i) => {
666
+ const v = plainCell(table.value(tag, i));
667
+ return isScalar(v) ? v : null;
668
+ });
669
+ out.set(key, target === "edge" ? withPairValues(snapshot, col) : col);
670
+ }
671
+ return out;
672
+ }
673
+ /**
674
+ * The style columns the block lists as booleans, as booleans: a format with no booleans (GML) holds them as 0 and 1
675
+ * (or their text).
676
+ * @param block - the block
677
+ * @param columns - the style columns per target, changed in place
678
+ */
679
+ function asBooleans(block, columns) {
680
+ for (const target of TARGETS) {
681
+ for (const key of block.booleans?.[target] ?? []) {
682
+ const col = columns[target].get(key);
683
+ if (col !== undefined) {
684
+ columns[target].set(key, col.map(asBoolean));
685
+ }
686
+ }
687
+ }
688
+ }
689
+ /**
690
+ * A value of a boolean style column as a boolean: 1 and 0, and their text, as GML and untyped formats hold them.
691
+ * @param v - the value read
692
+ * @returns the boolean, or the value when it is neither
693
+ */
694
+ function asBoolean(v) {
695
+ if (v === 1 || v === "1" || v === "true") {
696
+ return true;
697
+ }
698
+ return v === 0 || v === "0" || v === "false" ? false : v;
699
+ }
700
+ /**
701
+ * Inline node values in the order of the graph read back: by each node's id, when the block lists the order it wrote
702
+ * them in and the file read its nodes back in another.
703
+ * @param block - the block
704
+ * @param snapshot - the graph
705
+ * @param col - the values in the block's order
706
+ * @returns the values per node row
707
+ */
708
+ function inNodeOrder(block, snapshot, col) {
709
+ const { order } = block;
710
+ if (order === undefined || order.every((id, i) => id === String(snapshot.ids.idOf(i)))) {
711
+ return col;
712
+ }
713
+ const at = new Map();
714
+ order.forEach((id, i) => {
715
+ if (!at.has(id)) {
716
+ at.set(id, i);
717
+ }
718
+ });
719
+ return Array.from({ length: snapshot.nodeCount }, (_unused, i) => col[at.get(String(snapshot.ids.idOf(i))) ?? -1] ?? null);
720
+ }
721
+ /**
722
+ * Inline edge values, listed once per edge the file holds, per edge row: both halves of an undirected edge in a
723
+ * directed graph take the edge's value.
724
+ * @param snapshot - the graph
725
+ * @param col - the values per held edge
726
+ * @returns the values per edge row
727
+ */
728
+ function onEdgeRows(snapshot, col) {
729
+ const held = heldEdgeRows(snapshot);
730
+ if (held.length === snapshot.edgeCount) {
731
+ return col;
732
+ }
733
+ const out = new Array(snapshot.edgeCount).fill(null);
734
+ held.forEach((e, k) => {
735
+ out[e] = col[k] ?? null;
736
+ });
737
+ return withPairValues(snapshot, out);
738
+ }
739
+ /**
740
+ * Per-edge values with each half of an undirected edge in a directed graph given its other half's value where it has
741
+ * none: the file holds the edge once, and the format reads its values onto one half.
742
+ * @param snapshot - the graph
743
+ * @param col - the values per edge row
744
+ * @returns the values
745
+ */
746
+ function withPairValues(snapshot, col) {
747
+ const pair = snapshot.edges.byRole("pair");
748
+ if (pair === null) {
749
+ return col;
750
+ }
751
+ for (let i = 0; i < col.length; i++) {
752
+ if (col[i] === null && pair.isSet(i)) {
753
+ col[i] = col[pair.value(i)] ?? null;
754
+ }
755
+ }
756
+ return col;
757
+ }
758
+ /** The color property whose alpha carries an opacity, and that opacity, per target. */
759
+ const ALPHA_SLOT = {
760
+ node: ["fill", "fillOpacity"],
761
+ edge: ["color", "opacity"],
762
+ };
763
+ /**
764
+ * The native values with opacity 1 wherever the color is opaque (it has a color and no opacity) and the rules give a
765
+ * translucent opacity: a format that writes the opacity as the color's alpha states 1 with an opaque color.
766
+ * @param values - the native values of one target
767
+ * @param target - nodes or edges
768
+ * @param rules - the block's rules
769
+ * @param src - the values the rules read
770
+ * @param n - the element count
771
+ * @returns the values, the opacity column replaced where it changes
772
+ */
773
+ function opaqueColors(values, target, rules, src, n) {
774
+ const [colorProperty, opacityProperty] = ALPHA_SLOT[target];
775
+ const color = values[colorProperty];
776
+ if (color === undefined) {
777
+ return values;
778
+ }
779
+ const native = values[opacityProperty];
780
+ const resolved = resolveRules(rules, target, opacityProperty, src);
781
+ let out = null;
782
+ for (let i = 0; i < n; i++) {
783
+ const r = resolved[i];
784
+ if ((color[i] ?? null) !== null && (native?.[i] ?? null) === null && r !== null && r !== 1) {
785
+ out ?? (out = native === undefined ? new Array(n).fill(null) : [...native]);
786
+ out[i] = 1;
787
+ }
788
+ }
789
+ return out === null ? values : { ...values, [opacityProperty]: out };
790
+ }
791
+ /**
792
+ * A name not yet taken: the base, else the base with `#2`, `#3` and so on.
793
+ * @param taken - whether a name is taken
794
+ * @param base - the preferred name
795
+ * @returns the name
796
+ */
797
+ function freeName(taken, base) {
798
+ let name = base;
799
+ let k = 2;
800
+ while (taken(name)) {
801
+ name = `${base}#${String(k)}`;
802
+ k++;
803
+ }
804
+ return name;
805
+ }
806
+ /**
807
+ * Whether a property's values are text: an empty text draws what no text draws, so a format that holds no "unset"
808
+ * (CyCSV) reads one back as "".
809
+ * @param target - nodes or edges
810
+ * @param property - the property
811
+ * @returns true for text
812
+ */
813
+ function textProperty(target, property) {
814
+ return STYLE_PROPERTIES[target].get(property) === "text";
815
+ }
816
+ /**
817
+ * The elements whose native value differs from what the rules give: another program edited them. Where the rules
818
+ * give no value, the program's own drawing of an unset property, and an empty text, are no edit.
819
+ * @param values - the native values
820
+ * @param resolved - what the rules give
821
+ * @param unset - what the writing program draws for the unset property, or undefined
822
+ * @param text - whether the property is text
823
+ * @returns the edited values, null where an element is not edited; null when none is
824
+ */
825
+ function editedValues(values, resolved, unset, text) {
826
+ const empty = text ? "" : undefined;
827
+ let exceptions = null;
828
+ for (let i = 0; i < resolved.length; i++) {
829
+ const t = values[i] ?? null;
830
+ const unchanged = resolved[i] === null && (t === unset || t === empty);
831
+ if (t !== null && !within(t, resolved[i]) && !unchanged) {
832
+ exceptions ?? (exceptions = new Array(resolved.length).fill(null));
833
+ exceptions[i] = t;
834
+ }
835
+ }
836
+ return exceptions;
837
+ }
838
+ /**
839
+ * The passthrough mappings of the elements whose native value differs from what the rules give, each over a new
840
+ * exceptions column.
841
+ * @param own - the native per-element values by property
842
+ * @param rules - the block's rules
843
+ * @param target - nodes or edges
844
+ * @param src - what the rules read
845
+ * @param columns - the target's style columns, added to
846
+ * @param unsetOf - what the writing program draws for an unset property
847
+ * @returns the mappings by property, empty when nothing was edited
848
+ */
849
+ function exceptionMappings(own, rules, target, src, columns, unsetOf) {
850
+ const map = Object.create(null);
851
+ // in one order whatever order the reader found the properties in, so a file written again is the same
852
+ for (const [property, values] of Object.entries(own).sort(([a], [b]) => (a < b ? -1 : 1))) {
853
+ if (values === undefined) {
854
+ continue;
855
+ }
856
+ const resolved = resolveRules(rules, target, property, src);
857
+ const exceptions = editedValues(values, resolved, unsetOf(property), textProperty(target, property));
858
+ if (exceptions !== null) {
859
+ const key = freeName((k) => columns.has(k), `exceptions.${property}`);
860
+ columns.set(key, exceptions);
861
+ map[property] = { kind: "passthrough", by: { style: key } };
862
+ }
863
+ }
864
+ return map;
865
+ }
866
+ /**
867
+ * The styles a valid block describes, read against the graph it was imported into. The block's rules are the
868
+ * file's declared rules and read the tagged per-element values. Where the file's own native values are given, they
869
+ * are the truth: an element whose value differs from what the rules give (another program edited it) is written
870
+ * into one exceptions rule on top, so the styles stay exact and, with no edit, are the block's rules unchanged.
871
+ * @param block - a block `parseStyleBlock()` accepted for this graph
872
+ * @param snapshot - the graph
873
+ * @param format - the format the file was read as
874
+ * @param truth - the native per-element values per target and property, when the format has any
875
+ * @param notes - notes to carry (the reader's own)
876
+ * @param tool - the program whose drawing the native values describe: where the rules give an element no value and
877
+ * the file holds only what that program draws for an unset property (a font written with "plain" style), it is not
878
+ * an edit
879
+ * @param opacityInColor - whether the format writes a fill's and an edge's opacity as its color's alpha: a native
880
+ * color with no native opacity then states opacity 1 where the rules give a translucent one
881
+ * @returns the styles, or null when a style column the rules read is missing from the file
882
+ * @category Styles
883
+ */
884
+ export function blockStyles(block, snapshot, format, truth = {}, notes = [], tool = null, opacityInColor = false) {
885
+ const node = blockColumns(block, snapshot, "node");
886
+ const edge = blockColumns(block, snapshot, "edge");
887
+ if (node === null || edge === null) {
888
+ return null;
889
+ }
890
+ const columns = { node, edge };
891
+ asBooleans(block, columns);
892
+ const features = { node: featuresOf(snapshot, "node"), edge: featuresOf(snapshot, "edge") };
893
+ // a data column the file holds under another name is read there
894
+ const moved = { node: movedColumns(block, snapshot, "node"), edge: movedColumns(block, snapshot, "edge") };
895
+ const blockRules = block.rules.map((r) => (moved[r.target].size === 0 ? r : renameData(r, moved[r.target])));
896
+ const rules = [...blockRules];
897
+ for (const target of TARGETS) {
898
+ const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
899
+ const src = refSource(target, n, columns[target], features[target], snapshot);
900
+ const own = opacityInColor ? opaqueColors(truth[target] ?? {}, target, blockRules, src, n) : truth[target];
901
+ const unsetOf = (property) => (tool === null ? null : toolDefaults(tool))?.[target]?.[property]?.value;
902
+ const map = exceptionMappings(own ?? {}, blockRules, target, src, columns[target], unsetOf);
903
+ if (Object.keys(map).length > 0) {
904
+ // the block's own rules may hold an exceptions rule already (a file graphty wrote from an edited one)
905
+ const id = freeName((x) => rules.some((r) => r.id === x), `${target}.exceptions`);
906
+ rules.push({
907
+ id,
908
+ target,
909
+ role: "exceptions",
910
+ origin: "inferred",
911
+ where: { all: true },
912
+ map,
913
+ });
914
+ }
915
+ }
916
+ return {
917
+ styles: {
918
+ version: 1,
919
+ source: { format, dialect: "graphty", tool: "graphty" },
920
+ units: block.units,
921
+ graph: block.graph,
922
+ rules,
923
+ notes,
924
+ },
925
+ columns,
926
+ features,
927
+ fingerprint: styleFingerprint(snapshot),
928
+ };
929
+ }
930
+ //# sourceMappingURL=block.js.map