@graphty/graph-io 0.3.48 → 0.3.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (600) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-BRXsll0T.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-BRXsll0T.js.map} +1 -1
  3. package/dist/chunks/bends-BGXjv_U4.js +129 -0
  4. package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
  5. package/dist/chunks/{block-Cu22ewuS.js → block-yl0f_qLO.js} +931 -164
  6. package/dist/chunks/block-yl0f_qLO.js.map +1 -0
  7. package/dist/chunks/choose-CczZJaX_.js +717 -0
  8. package/dist/chunks/choose-CczZJaX_.js.map +1 -0
  9. package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/{context-cgmmOxZ2.js → context-DizmppHy.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-DizmppHy.js.map} +1 -1
  15. package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
  16. package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
  17. package/dist/chunks/{credentials-BiQsnMTb.js → credentials-CmvJXYeH.js} +67 -16
  18. package/dist/chunks/credentials-CmvJXYeH.js.map +1 -0
  19. package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
  20. package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-Dhez_Cew.js} +11 -2
  24. package/dist/chunks/descriptor-Dhez_Cew.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-7Jkpg0yd.js} +1788 -133
  26. package/dist/chunks/emit-7Jkpg0yd.js.map +1 -0
  27. package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
  28. package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
  29. package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
  30. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  31. package/dist/chunks/{exporter-ChjL5fmP.js → exporter-1Ajud15J.js} +9 -8
  32. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-1Ajud15J.js.map} +1 -1
  33. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-B6yvL3wy.js} +7 -7
  34. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-B6yvL3wy.js.map} +1 -1
  35. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  36. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-CA5q8ROP.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-CA5q8ROP.js.map} +1 -1
  39. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-CQQZFJ2v.js} +1284 -156
  40. package/dist/chunks/exporter-CQQZFJ2v.js.map +1 -0
  41. package/dist/chunks/format-BXiAb-1h.js +408 -0
  42. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  43. package/dist/chunks/{generic-CP6YD34u.js → generic-Dc21MAdg.js} +387 -31
  44. package/dist/chunks/generic-Dc21MAdg.js.map +1 -0
  45. package/dist/chunks/{importer-B87_fmVx.js → importer-C6NVpCXp.js} +327 -84
  46. package/dist/chunks/importer-C6NVpCXp.js.map +1 -0
  47. package/dist/chunks/{importer-DPZDN40-.js → importer-CKFe4q54.js} +25 -17
  48. package/dist/chunks/importer-CKFe4q54.js.map +1 -0
  49. package/dist/chunks/{importer-Bji2MeWr.js → importer-CKbUbsJA.js} +13 -10
  50. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-CKbUbsJA.js.map} +1 -1
  51. package/dist/chunks/{importer-CB_zV5_L.js → importer-ClCsdgTJ.js} +208 -1104
  52. package/dist/chunks/importer-ClCsdgTJ.js.map +1 -0
  53. package/dist/chunks/{importer-e3huMZbm.js → importer-CyVZTrf0.js} +14 -10
  54. package/dist/chunks/importer-CyVZTrf0.js.map +1 -0
  55. package/dist/chunks/{importer-CVT-JyDE.js → importer-DgG4v1Ms.js} +1537 -355
  56. package/dist/chunks/importer-DgG4v1Ms.js.map +1 -0
  57. package/dist/chunks/{importer-Cyy6UseH.js → importer-asFUrIsj.js} +66 -13
  58. package/dist/chunks/importer-asFUrIsj.js.map +1 -0
  59. package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
  60. package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
  61. package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
  62. package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  63. package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-IVRq2Uoo.js} +282 -74
  64. package/dist/chunks/lexicon-IVRq2Uoo.js.map +1 -0
  65. package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
  66. package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  67. package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
  68. package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
  69. package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
  70. package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
  71. package/dist/chunks/round-trip-Cy3_SHRZ.js +79 -0
  72. package/dist/chunks/round-trip-Cy3_SHRZ.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-BXwVbza3.js} +5 -5
  74. package/dist/chunks/sigv4-BXwVbza3.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CAVmBLgp.js} +1237 -138
  76. package/dist/chunks/styles-CAVmBLgp.js.map +1 -0
  77. package/dist/chunks/styles-CPczw1Jz.js +1928 -0
  78. package/dist/chunks/styles-CPczw1Jz.js.map +1 -0
  79. package/dist/chunks/styles-boK6Ln54.js +2847 -0
  80. package/dist/chunks/styles-boK6Ln54.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-XeFBQ6VS.js} +506 -175
  82. package/dist/chunks/styles-yed-XeFBQ6VS.js.map +1 -0
  83. package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
  84. package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
  85. package/dist/csv.js +7 -7
  86. package/dist/cx.js +2 -2
  87. package/dist/cx2.js +2 -2
  88. package/dist/cys.js +1 -1
  89. package/dist/dot.js +8 -4
  90. package/dist/dot.js.map +1 -1
  91. package/dist/gexf.js +42 -12
  92. package/dist/gexf.js.map +1 -1
  93. package/dist/gml.js +848 -194
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +230 -193
  96. package/dist/graph-io.js.map +1 -1
  97. package/dist/graphml.js +3 -3
  98. package/dist/json.js +3 -2
  99. package/dist/neo4j.js +6 -6
  100. package/dist/obo.js +1 -1
  101. package/dist/pajek.js +1 -1
  102. package/dist/positions.js +45 -3
  103. package/dist/positions.js.map +1 -1
  104. package/dist/sources-cypher.js +141 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +32 -6
  108. package/dist/sources-rest.js.map +1 -1
  109. package/dist/sources-sparql.d.ts +1 -0
  110. package/dist/sources-sparql.js +439 -0
  111. package/dist/sources-sparql.js.map +1 -0
  112. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  113. package/dist/src/formats/cx/importer.js +5 -1
  114. package/dist/src/formats/cx/importer.js.map +1 -1
  115. package/dist/src/formats/cx/styles.d.ts +24 -1
  116. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  117. package/dist/src/formats/cx/styles.js +117 -11
  118. package/dist/src/formats/cx/styles.js.map +1 -1
  119. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  120. package/dist/src/formats/cx2/importer.js +1 -0
  121. package/dist/src/formats/cx2/importer.js.map +1 -1
  122. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  123. package/dist/src/formats/cx2/styles.js +3 -1
  124. package/dist/src/formats/cx2/styles.js.map +1 -1
  125. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cys/importer.js +1 -0
  127. package/dist/src/formats/cys/importer.js.map +1 -1
  128. package/dist/src/formats/cys/styles.d.ts +2 -0
  129. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cys/styles.js +15 -7
  131. package/dist/src/formats/cys/styles.js.map +1 -1
  132. package/dist/src/formats/dot/drawing.d.ts +98 -0
  133. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  134. package/dist/src/formats/dot/drawing.js +734 -0
  135. package/dist/src/formats/dot/drawing.js.map +1 -0
  136. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  137. package/dist/src/formats/dot/exporter.js +34 -2
  138. package/dist/src/formats/dot/exporter.js.map +1 -1
  139. package/dist/src/formats/dot/importer.d.ts +6 -1
  140. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  141. package/dist/src/formats/dot/importer.js +170 -33
  142. package/dist/src/formats/dot/importer.js.map +1 -1
  143. package/dist/src/formats/dot/index.d.ts +3 -1
  144. package/dist/src/formats/dot/index.d.ts.map +1 -1
  145. package/dist/src/formats/dot/index.js +2 -1
  146. package/dist/src/formats/dot/index.js.map +1 -1
  147. package/dist/src/formats/dot/label-places.d.ts +41 -0
  148. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  149. package/dist/src/formats/dot/label-places.js +185 -0
  150. package/dist/src/formats/dot/label-places.js.map +1 -0
  151. package/dist/src/formats/dot/names.d.ts +13 -0
  152. package/dist/src/formats/dot/names.d.ts.map +1 -1
  153. package/dist/src/formats/dot/names.js +13 -0
  154. package/dist/src/formats/dot/names.js.map +1 -1
  155. package/dist/src/formats/dot/record.d.ts +50 -0
  156. package/dist/src/formats/dot/record.d.ts.map +1 -0
  157. package/dist/src/formats/dot/record.js +275 -0
  158. package/dist/src/formats/dot/record.js.map +1 -0
  159. package/dist/src/formats/dot/styles.d.ts +72 -2
  160. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  161. package/dist/src/formats/dot/styles.js +1500 -119
  162. package/dist/src/formats/dot/styles.js.map +1 -1
  163. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  164. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  165. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  166. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  167. package/dist/src/formats/gexf/importer.d.ts +7 -0
  168. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  169. package/dist/src/formats/gexf/importer.js +41 -5
  170. package/dist/src/formats/gexf/importer.js.map +1 -1
  171. package/dist/src/formats/gexf/preview.d.ts +77 -0
  172. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  173. package/dist/src/formats/gexf/preview.js +191 -0
  174. package/dist/src/formats/gexf/preview.js.map +1 -0
  175. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  176. package/dist/src/formats/gexf/schema.js +2 -1
  177. package/dist/src/formats/gexf/schema.js.map +1 -1
  178. package/dist/src/formats/gexf/styles.d.ts +58 -31
  179. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  180. package/dist/src/formats/gexf/styles.js +848 -225
  181. package/dist/src/formats/gexf/styles.js.map +1 -1
  182. package/dist/src/formats/gml/importer.d.ts +5 -2
  183. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  184. package/dist/src/formats/gml/importer.js +258 -71
  185. package/dist/src/formats/gml/importer.js.map +1 -1
  186. package/dist/src/formats/gml/index.d.ts +1 -1
  187. package/dist/src/formats/gml/index.d.ts.map +1 -1
  188. package/dist/src/formats/gml/index.js +1 -1
  189. package/dist/src/formats/gml/index.js.map +1 -1
  190. package/dist/src/formats/gml/positions.d.ts +7 -0
  191. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  192. package/dist/src/formats/gml/positions.js +29 -7
  193. package/dist/src/formats/gml/positions.js.map +1 -1
  194. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  195. package/dist/src/formats/gml/styles.js +754 -102
  196. package/dist/src/formats/gml/styles.js.map +1 -1
  197. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/styles-plain.js +6 -10
  199. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  200. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  201. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  202. package/dist/src/formats/graphml/styles-yed.js +695 -164
  203. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  204. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  205. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  206. package/dist/src/formats/graphml/styles-yfiles3.js +431 -64
  207. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  208. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  209. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  210. package/dist/src/formats/graphml/yfiles.js +16 -6
  211. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  212. package/dist/src/formats/json/dialect.d.ts +3 -2
  213. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  214. package/dist/src/formats/json/dialect.js +39 -5
  215. package/dist/src/formats/json/dialect.js.map +1 -1
  216. package/dist/src/formats/json/importer.d.ts +13 -2
  217. package/dist/src/formats/json/importer.d.ts.map +1 -1
  218. package/dist/src/formats/json/importer.js +42 -6
  219. package/dist/src/formats/json/importer.js.map +1 -1
  220. package/dist/src/formats/json/index.d.ts +1 -1
  221. package/dist/src/formats/json/index.d.ts.map +1 -1
  222. package/dist/src/formats/json/index.js +1 -1
  223. package/dist/src/formats/json/index.js.map +1 -1
  224. package/dist/src/formats/json/positions.d.ts +5 -2
  225. package/dist/src/formats/json/positions.d.ts.map +1 -1
  226. package/dist/src/formats/json/positions.js +20 -4
  227. package/dist/src/formats/json/positions.js.map +1 -1
  228. package/dist/src/formats/json/styles.d.ts +12 -1
  229. package/dist/src/formats/json/styles.d.ts.map +1 -1
  230. package/dist/src/formats/json/styles.js +1843 -136
  231. package/dist/src/formats/json/styles.js.map +1 -1
  232. package/dist/src/formats/pajek/draw.d.ts +104 -0
  233. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  234. package/dist/src/formats/pajek/draw.js +382 -0
  235. package/dist/src/formats/pajek/draw.js.map +1 -0
  236. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  237. package/dist/src/formats/pajek/exporter.js +70 -51
  238. package/dist/src/formats/pajek/exporter.js.map +1 -1
  239. package/dist/src/formats/pajek/importer.d.ts +9 -0
  240. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  241. package/dist/src/formats/pajek/importer.js +233 -102
  242. package/dist/src/formats/pajek/importer.js.map +1 -1
  243. package/dist/src/formats/pajek/index.d.ts +1 -0
  244. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  245. package/dist/src/formats/pajek/index.js.map +1 -1
  246. package/dist/src/formats/pajek/styles.d.ts +15 -7
  247. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  248. package/dist/src/formats/pajek/styles.js +1395 -114
  249. package/dist/src/formats/pajek/styles.js.map +1 -1
  250. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  251. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  252. package/dist/src/formats/pajek/syntax.js +26 -2
  253. package/dist/src/formats/pajek/syntax.js.map +1 -1
  254. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  255. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  256. package/dist/src/formats/xgmml/emit.js +65 -5
  257. package/dist/src/formats/xgmml/emit.js.map +1 -1
  258. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  259. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  260. package/dist/src/formats/xgmml/styles.js +277 -60
  261. package/dist/src/formats/xgmml/styles.js.map +1 -1
  262. package/dist/src/index.d.ts +6 -5
  263. package/dist/src/index.d.ts.map +1 -1
  264. package/dist/src/index.js +6 -5
  265. package/dist/src/index.js.map +1 -1
  266. package/dist/src/positions/convert.d.ts.map +1 -1
  267. package/dist/src/positions/convert.js +11 -1
  268. package/dist/src/positions/convert.js.map +1 -1
  269. package/dist/src/positions/extract.d.ts.map +1 -1
  270. package/dist/src/positions/extract.js +53 -1
  271. package/dist/src/positions/extract.js.map +1 -1
  272. package/dist/src/positions/index.d.ts +1 -1
  273. package/dist/src/positions/index.d.ts.map +1 -1
  274. package/dist/src/positions/types.d.ts +59 -0
  275. package/dist/src/positions/types.d.ts.map +1 -1
  276. package/dist/src/sources/builtins.d.ts +1 -1
  277. package/dist/src/sources/builtins.d.ts.map +1 -1
  278. package/dist/src/sources/builtins.js +8 -2
  279. package/dist/src/sources/builtins.js.map +1 -1
  280. package/dist/src/sources/context.d.ts.map +1 -1
  281. package/dist/src/sources/context.js +1 -0
  282. package/dist/src/sources/context.js.map +1 -1
  283. package/dist/src/sources/credentials.d.ts +50 -1
  284. package/dist/src/sources/credentials.d.ts.map +1 -1
  285. package/dist/src/sources/credentials.js +69 -0
  286. package/dist/src/sources/credentials.js.map +1 -1
  287. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  288. package/dist/src/sources/cypher/descriptor.js +5 -0
  289. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  290. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  291. package/dist/src/sources/cypher/index.js +125 -18
  292. package/dist/src/sources/cypher/index.js.map +1 -1
  293. package/dist/src/sources/cypher/params.d.ts +1 -1
  294. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  295. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  296. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  297. package/dist/src/sources/cypher/query-builder.js +31 -0
  298. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  299. package/dist/src/sources/ids.d.ts +5 -0
  300. package/dist/src/sources/ids.d.ts.map +1 -1
  301. package/dist/src/sources/ids.js +5 -0
  302. package/dist/src/sources/ids.js.map +1 -1
  303. package/dist/src/sources/params.d.ts +3 -0
  304. package/dist/src/sources/params.d.ts.map +1 -1
  305. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  306. package/dist/src/sources/rest/descriptor.js +9 -0
  307. package/dist/src/sources/rest/descriptor.js.map +1 -1
  308. package/dist/src/sources/rest/openalex.d.ts +4 -2
  309. package/dist/src/sources/rest/openalex.d.ts.map +1 -1
  310. package/dist/src/sources/rest/openalex.js +4 -2
  311. package/dist/src/sources/rest/openalex.js.map +1 -1
  312. package/dist/src/sources/rest/source.d.ts.map +1 -1
  313. package/dist/src/sources/rest/source.js +38 -0
  314. package/dist/src/sources/rest/source.js.map +1 -1
  315. package/dist/src/sources/run.d.ts +2 -0
  316. package/dist/src/sources/run.d.ts.map +1 -1
  317. package/dist/src/sources/run.js +30 -3
  318. package/dist/src/sources/run.js.map +1 -1
  319. package/dist/src/sources/sigv4.d.ts +5 -3
  320. package/dist/src/sources/sigv4.d.ts.map +1 -1
  321. package/dist/src/sources/sigv4.js +6 -4
  322. package/dist/src/sources/sigv4.js.map +1 -1
  323. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  324. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  325. package/dist/src/sources/sparql/descriptor.js +64 -0
  326. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  327. package/dist/src/sources/sparql/index.d.ts +28 -0
  328. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  329. package/dist/src/sources/sparql/index.js +327 -0
  330. package/dist/src/sources/sparql/index.js.map +1 -0
  331. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  332. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  333. package/dist/src/sources/sparql/ntriples.js +180 -0
  334. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  335. package/dist/src/sources/sparql/params.d.ts +27 -0
  336. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  337. package/dist/src/sources/sparql/params.js +5 -0
  338. package/dist/src/sources/sparql/params.js.map +1 -0
  339. package/dist/src/sources/sparql/query.d.ts +73 -0
  340. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  341. package/dist/src/sources/sparql/query.js +164 -0
  342. package/dist/src/sources/sparql/query.js.map +1 -0
  343. package/dist/src/sources/types.d.ts +60 -0
  344. package/dist/src/sources/types.d.ts.map +1 -1
  345. package/dist/src/styles/annotations.d.ts +61 -5
  346. package/dist/src/styles/annotations.d.ts.map +1 -1
  347. package/dist/src/styles/annotations.js +130 -22
  348. package/dist/src/styles/annotations.js.map +1 -1
  349. package/dist/src/styles/canon/bends.d.ts +46 -0
  350. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  351. package/dist/src/styles/canon/bends.js +123 -0
  352. package/dist/src/styles/canon/bends.js.map +1 -1
  353. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  354. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  355. package/dist/src/styles/canon/color-tables.js +10 -4
  356. package/dist/src/styles/canon/color-tables.js.map +1 -1
  357. package/dist/src/styles/canon/color.d.ts +3 -1
  358. package/dist/src/styles/canon/color.d.ts.map +1 -1
  359. package/dist/src/styles/canon/color.js +103 -3
  360. package/dist/src/styles/canon/color.js.map +1 -1
  361. package/dist/src/styles/canon/enums.d.ts +2 -2
  362. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  363. package/dist/src/styles/canon/enums.js +89 -7
  364. package/dist/src/styles/canon/enums.js.map +1 -1
  365. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  366. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  367. package/dist/src/styles/canon/graphviz.js +57 -9
  368. package/dist/src/styles/canon/graphviz.js.map +1 -1
  369. package/dist/src/styles/canon/number.d.ts +8 -0
  370. package/dist/src/styles/canon/number.d.ts.map +1 -1
  371. package/dist/src/styles/canon/number.js +18 -0
  372. package/dist/src/styles/canon/number.js.map +1 -1
  373. package/dist/src/styles/canon/text.d.ts +29 -2
  374. package/dist/src/styles/canon/text.d.ts.map +1 -1
  375. package/dist/src/styles/canon/text.js +156 -16
  376. package/dist/src/styles/canon/text.js.map +1 -1
  377. package/dist/src/styles/codes.d.ts +2 -0
  378. package/dist/src/styles/codes.d.ts.map +1 -1
  379. package/dist/src/styles/codes.js +2 -0
  380. package/dist/src/styles/codes.js.map +1 -1
  381. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  382. package/dist/src/styles/cyjs/cascade.js +1139 -79
  383. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  384. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  385. package/dist/src/styles/cyjs/defaults-table.js +4 -0
  386. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  387. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  388. package/dist/src/styles/cyjs/emit.js +232 -10
  389. package/dist/src/styles/cyjs/emit.js.map +1 -1
  390. package/dist/src/styles/cyjs/face.d.ts +20 -0
  391. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  392. package/dist/src/styles/cyjs/face.js +332 -0
  393. package/dist/src/styles/cyjs/face.js.map +1 -0
  394. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  395. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  396. package/dist/src/styles/cyjs/mappers.js +475 -26
  397. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  398. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  399. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  400. package/dist/src/styles/cyjs/routes.js +360 -0
  401. package/dist/src/styles/cyjs/routes.js.map +1 -0
  402. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  403. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  404. package/dist/src/styles/cytoscape/charts.js +560 -0
  405. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  406. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  407. package/dist/src/styles/cytoscape/emit.js +156 -48
  408. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  409. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  410. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  411. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  412. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  413. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  414. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  415. package/dist/src/styles/cytoscape/mappings.js +92 -0
  416. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  417. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  418. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  419. package/dist/src/styles/cytoscape/resolve.js +623 -17
  420. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  421. package/dist/src/styles/defaults.d.ts +46 -26
  422. package/dist/src/styles/defaults.d.ts.map +1 -1
  423. package/dist/src/styles/defaults.js +308 -71
  424. package/dist/src/styles/defaults.js.map +1 -1
  425. package/dist/src/styles/index.d.ts +4 -3
  426. package/dist/src/styles/index.d.ts.map +1 -1
  427. package/dist/src/styles/index.js +3 -2
  428. package/dist/src/styles/index.js.map +1 -1
  429. package/dist/src/styles/internal.d.ts +1 -0
  430. package/dist/src/styles/internal.d.ts.map +1 -1
  431. package/dist/src/styles/internal.js +1 -0
  432. package/dist/src/styles/internal.js.map +1 -1
  433. package/dist/src/styles/io/generic.d.ts.map +1 -1
  434. package/dist/src/styles/io/generic.js +56 -16
  435. package/dist/src/styles/io/generic.js.map +1 -1
  436. package/dist/src/styles/io/round-trip.d.ts +56 -0
  437. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  438. package/dist/src/styles/io/round-trip.js +138 -0
  439. package/dist/src/styles/io/round-trip.js.map +1 -0
  440. package/dist/src/styles/io/writer.d.ts.map +1 -1
  441. package/dist/src/styles/io/writer.js +6 -1
  442. package/dist/src/styles/io/writer.js.map +1 -1
  443. package/dist/src/styles/notes.d.ts.map +1 -1
  444. package/dist/src/styles/notes.js +1 -0
  445. package/dist/src/styles/notes.js.map +1 -1
  446. package/dist/src/styles/plan/features.d.ts +1 -1
  447. package/dist/src/styles/plan/features.d.ts.map +1 -1
  448. package/dist/src/styles/plan/features.js +22 -2
  449. package/dist/src/styles/plan/features.js.map +1 -1
  450. package/dist/src/styles/plan/index.d.ts +1 -1
  451. package/dist/src/styles/plan/index.d.ts.map +1 -1
  452. package/dist/src/styles/plan/index.js +1 -1
  453. package/dist/src/styles/plan/index.js.map +1 -1
  454. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  455. package/dist/src/styles/plan/plan.js +61 -4
  456. package/dist/src/styles/plan/plan.js.map +1 -1
  457. package/dist/src/styles/plan/resolve.d.ts +11 -0
  458. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  459. package/dist/src/styles/plan/resolve.js +40 -4
  460. package/dist/src/styles/plan/resolve.js.map +1 -1
  461. package/dist/src/styles/slots.d.ts +14 -0
  462. package/dist/src/styles/slots.d.ts.map +1 -0
  463. package/dist/src/styles/slots.js +20 -0
  464. package/dist/src/styles/slots.js.map +1 -0
  465. package/dist/src/styles/types.d.ts +687 -6
  466. package/dist/src/styles/types.d.ts.map +1 -1
  467. package/dist/src/styles/vocabulary.d.ts +3 -2
  468. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  469. package/dist/src/styles/vocabulary.js +224 -0
  470. package/dist/src/styles/vocabulary.js.map +1 -1
  471. package/dist/styles.js +30 -239
  472. package/dist/styles.js.map +1 -1
  473. package/dist/xgmml.js +3 -3
  474. package/package.json +27 -7
  475. package/src/formats/cx/importer.ts +6 -1
  476. package/src/formats/cx/styles.ts +143 -9
  477. package/src/formats/cx2/importer.ts +1 -0
  478. package/src/formats/cx2/styles.ts +3 -1
  479. package/src/formats/cys/importer.ts +1 -0
  480. package/src/formats/cys/styles.ts +27 -5
  481. package/src/formats/dot/drawing.ts +799 -0
  482. package/src/formats/dot/exporter.ts +37 -1
  483. package/src/formats/dot/importer.ts +192 -36
  484. package/src/formats/dot/index.ts +3 -1
  485. package/src/formats/dot/label-places.ts +241 -0
  486. package/src/formats/dot/names.ts +15 -0
  487. package/src/formats/dot/record.ts +336 -0
  488. package/src/formats/dot/styles.ts +1702 -149
  489. package/src/formats/gexf/dialog-metrics.ts +61 -0
  490. package/src/formats/gexf/importer.ts +50 -5
  491. package/src/formats/gexf/preview.ts +217 -0
  492. package/src/formats/gexf/schema.ts +2 -1
  493. package/src/formats/gexf/styles.ts +1099 -245
  494. package/src/formats/gml/importer.ts +291 -76
  495. package/src/formats/gml/index.ts +1 -1
  496. package/src/formats/gml/positions.ts +29 -7
  497. package/src/formats/gml/styles.ts +852 -110
  498. package/src/formats/graphml/styles-plain.ts +6 -15
  499. package/src/formats/graphml/styles-yed.ts +765 -176
  500. package/src/formats/graphml/styles-yfiles3.ts +487 -63
  501. package/src/formats/graphml/yfiles.ts +19 -6
  502. package/src/formats/json/dialect.ts +41 -5
  503. package/src/formats/json/importer.ts +59 -7
  504. package/src/formats/json/index.ts +1 -0
  505. package/src/formats/json/positions.ts +22 -5
  506. package/src/formats/json/styles.ts +2123 -171
  507. package/src/formats/pajek/draw.ts +469 -0
  508. package/src/formats/pajek/exporter.ts +81 -49
  509. package/src/formats/pajek/importer.ts +278 -103
  510. package/src/formats/pajek/index.ts +1 -0
  511. package/src/formats/pajek/styles.ts +1506 -133
  512. package/src/formats/pajek/syntax.ts +27 -2
  513. package/src/formats/xgmml/emit.ts +73 -5
  514. package/src/formats/xgmml/styles.ts +330 -71
  515. package/src/index.ts +12 -1
  516. package/src/positions/convert.ts +12 -1
  517. package/src/positions/extract.ts +55 -1
  518. package/src/positions/index.ts +1 -0
  519. package/src/positions/types.ts +60 -0
  520. package/src/sources/builtins.ts +8 -1
  521. package/src/sources/context.ts +1 -0
  522. package/src/sources/credentials.ts +90 -1
  523. package/src/sources/cypher/descriptor.ts +7 -1
  524. package/src/sources/cypher/index.ts +149 -18
  525. package/src/sources/cypher/params.ts +1 -1
  526. package/src/sources/cypher/query-builder.ts +33 -0
  527. package/src/sources/ids.ts +6 -0
  528. package/src/sources/params.ts +3 -0
  529. package/src/sources/rest/descriptor.ts +9 -0
  530. package/src/sources/rest/openalex.ts +4 -2
  531. package/src/sources/rest/source.ts +41 -0
  532. package/src/sources/run.ts +35 -3
  533. package/src/sources/sigv4.ts +6 -4
  534. package/src/sources/sparql/descriptor.ts +67 -0
  535. package/src/sources/sparql/index.ts +371 -0
  536. package/src/sources/sparql/ntriples.ts +219 -0
  537. package/src/sources/sparql/params.ts +28 -0
  538. package/src/sources/sparql/query.ts +216 -0
  539. package/src/sources/types.ts +68 -0
  540. package/src/styles/annotations.ts +201 -27
  541. package/src/styles/canon/bends.ts +137 -0
  542. package/src/styles/canon/color-tables.ts +10 -4
  543. package/src/styles/canon/color.ts +105 -3
  544. package/src/styles/canon/enums.ts +107 -8
  545. package/src/styles/canon/graphviz.ts +71 -10
  546. package/src/styles/canon/number.ts +19 -0
  547. package/src/styles/canon/text.ts +187 -16
  548. package/src/styles/codes.ts +2 -0
  549. package/src/styles/cyjs/cascade.ts +1303 -84
  550. package/src/styles/cyjs/defaults-table.ts +4 -0
  551. package/src/styles/cyjs/emit.ts +268 -14
  552. package/src/styles/cyjs/face.ts +372 -0
  553. package/src/styles/cyjs/mappers.ts +506 -27
  554. package/src/styles/cyjs/routes.ts +432 -0
  555. package/src/styles/cytoscape/charts.ts +684 -0
  556. package/src/styles/cytoscape/emit.ts +170 -48
  557. package/src/styles/cytoscape/lexicon.ts +431 -78
  558. package/src/styles/cytoscape/mappings.ts +108 -0
  559. package/src/styles/cytoscape/resolve.ts +741 -17
  560. package/src/styles/defaults.ts +417 -108
  561. package/src/styles/index.ts +5 -0
  562. package/src/styles/internal.ts +1 -0
  563. package/src/styles/io/generic.ts +79 -23
  564. package/src/styles/io/round-trip.ts +202 -0
  565. package/src/styles/io/writer.ts +6 -1
  566. package/src/styles/notes.ts +1 -0
  567. package/src/styles/plan/features.ts +23 -2
  568. package/src/styles/plan/index.ts +1 -1
  569. package/src/styles/plan/plan.ts +69 -5
  570. package/src/styles/plan/resolve.ts +47 -4
  571. package/src/styles/slots.ts +25 -0
  572. package/src/styles/types.ts +698 -5
  573. package/src/styles/vocabulary.ts +232 -2
  574. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  575. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  576. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  577. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  578. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  579. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  580. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  581. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  582. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  583. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  584. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  585. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  586. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  587. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  588. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  589. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  590. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  591. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  592. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  593. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  594. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  595. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  596. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  597. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  598. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  599. package/dist/chunks/writer-DvHTl36J.js +0 -449
  600. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -1,15 +1,272 @@
1
1
  import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
2
- import { L as LOSS, c as capabilities, r as resolveExportOptions, C as sanitizeIds, p as pairFolding, a as checkCapabilities, e as explicitWeights, O as canonicalId, R as RENAMED_CODE, d as resolveImportOptions, f as reportUnusedOptions, h as graphChosen, g as reportSinkOptions, i as DirectionResolver, I as IdCoercer, u as uniqueColumnName, j as declareResolved, P as coerceIdText, m as isWeightField, o as parseWeightText } from "./export-CZ7VRm4I.js";
3
- import { f as isPajekLabel, g as quotePajekLabel } from "./escape-DH2Egt-l.js";
4
- import { i as idText, b as formatNumber, d as formatDecimal, f as formatF32, c as formatInteger } from "./format-BMS-1Nxb.js";
5
- import { p as plural, a as agree, P as PRECISION_CODE, l as DUPLICATE_ATTRIBUTE_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, I as ID_MERGED_CODE, k as DUPLICATE_NODE_CODE, Q as SYNTAX_CODE, W as AMBIGUOUS_GRAPH_NAME_CODE, Y as GRAPH_NOT_FOUND_CODE, i as MULTIPLE_GRAPHS_CODE, s as UNKNOWN_ENCODING_CODE, t as ENCODING_FALLBACK_CODE, u as INVALID_ENCODING_CODE, v as INVALID_UTF8_CODE, y as ELEMENT_ISSUE, z as INPUT_ISSUE, K as ImportReportBuilder } from "./report-CgdsL9Hb.js";
6
- import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, a as isNumericText, T as TextCellWriter } from "./text-BuKQVMz2.js";
2
+ import { p as pairFolding, i as idText, b as formatNumber, d as formatDecimal, f as formatF32, c as formatInteger, D as DirectionResolver } from "./format-BXiAb-1h.js";
3
+ import { h as isPajekLabel, j as quotePajekLabel } from "./escape-CuCIzNMB.js";
4
+ import { e as explicitWeights, L as LOSS, c as capabilities, r as resolveExportOptions, z as sanitizeIds, a as checkCapabilities, H as canonicalId, R as RENAMED_CODE, b as resolveImportOptions, d as reportUnusedOptions, h as graphChosen, f as reportSinkOptions, I as IdCoercer, u as uniqueColumnName, i as declareResolved, Q as coerceIdText, k as isWeightField, p as parseWeightText } from "./export-Cha4dRFz.js";
5
+ import { p as plural, a as agree, P as PRECISION_CODE, l as DUPLICATE_ATTRIBUTE_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, I as ID_MERGED_CODE, k as DUPLICATE_NODE_CODE, Q as SYNTAX_CODE, W as AMBIGUOUS_GRAPH_NAME_CODE, Y as GRAPH_NOT_FOUND_CODE, i as MULTIPLE_GRAPHS_CODE, s as UNKNOWN_ENCODING_CODE, t as ENCODING_FALLBACK_CODE, u as INVALID_ENCODING_CODE, v as INVALID_UTF8_CODE, y as ELEMENT_ISSUE, z as INPUT_ISSUE, K as ImportReportBuilder } from "./report-CwMfYa9J.js";
6
+ import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, a as isNumericText, T as TextCellWriter } from "./text-ystE2bYi.js";
7
7
  import { j as joinText, e as encodeChunks } from "./writer-DxjgHwSe.js";
8
- import { i as importChosenGraph } from "./choose-Cdx6Enl2.js";
9
- import { L as LineReader, b as throwIfAborted } from "./input-Ccg9I22A.js";
10
- import { w as writeStyleBlock, c as styleBlockLosses, u as StyleNotes, p as plainCell, v as parseStyleBlock, s as styleFingerprint, x as blockStyles, r as resolveStyles, o as canonText, l as canonEnum, h as canonNumber, g as canonColor, y as colorOpacity, D as DVIPS_COLORS } from "./block-Cu22ewuS.js";
11
- import { S as StyleApproximations } from "./approximations-C2riR4NT.js";
12
- import { v as valueColumns } from "./styles-yed-Cs1nmrjn.js";
8
+ import { p as postscriptFont, f as graphvizFontName, i as importChosenGraph } from "./choose-CczZJaX_.js";
9
+ import { L as LineReader, b as throwIfAborted } from "./input-CAxt_aV-.js";
10
+ import { A as writeStyleBlock, B as styleBlockLosses, h as StyleNotes, p as plainCell, f as canonText, a as canonEnum, d as canonColor, e as colorOpacity, c as canonNumber, n as noteAt, b as STYLE_ISSUE, y as toolDefaults, L as DVIPS_COLORS } from "./block-yl0f_qLO.js";
11
+ import { S as StyleApproximations } from "./approximations-BRXsll0T.js";
12
+ import { e as elementValues, t as takeFromBlock } from "./round-trip-Cy3_SHRZ.js";
13
+ import { v as valueColumns } from "./styles-yed-XeFBQ6VS.js";
14
+ const PAJEK_WINDOW = 500;
15
+ function resolvePajekDraw(option) {
16
+ if (option === void 0) {
17
+ return null;
18
+ }
19
+ const bad = (found) => {
20
+ throw new GraphFormatError("E_UNSUPPORTED", "option pajekDraw: not an object of Pajek draw settings", {
21
+ option: "pajekDraw",
22
+ found
23
+ });
24
+ };
25
+ if (typeof option !== "object" || option === null || Array.isArray(option)) {
26
+ return bad(option);
27
+ }
28
+ const o = option;
29
+ const num = (v, fallback, positive) => {
30
+ if (v === void 0) {
31
+ return fallback;
32
+ }
33
+ if (typeof v !== "number" || !Number.isFinite(v)) {
34
+ return bad(v);
35
+ }
36
+ const inRange = positive ? v > 0 : v >= 0;
37
+ return inRange ? v : bad(v);
38
+ };
39
+ const ini = /* @__PURE__ */ new Map();
40
+ for (const [name, value] of Object.entries(o.ini ?? {})) {
41
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
42
+ return bad(value);
43
+ }
44
+ ini.set(name, String(value));
45
+ }
46
+ return {
47
+ width: num(o.width, PAJEK_WINDOW, true),
48
+ height: num(o.height, PAJEK_WINDOW, true),
49
+ partition: num(o.partition, 0, false),
50
+ vector: num(o.vector, 0, false),
51
+ vector2: num(o.vector2, 0, false),
52
+ ini
53
+ };
54
+ }
55
+ function flag(draw, name) {
56
+ const v = draw.ini.get(name);
57
+ return v !== void 0 && v !== "0" && v !== "false";
58
+ }
59
+ function drawsLineLabels(draw) {
60
+ return draw !== null && flag(draw, "Form8.withLabels1");
61
+ }
62
+ function drawsStraightLines(draw) {
63
+ return draw !== null && flag(draw, "Form10.StraightLinesOnly1");
64
+ }
65
+ function iniNumber(draw, name) {
66
+ const v = draw.ini.get(name);
67
+ const n = v === void 0 || v.trim() === "" ? Number.NaN : Number(v);
68
+ return Number.isFinite(n) ? n : null;
69
+ }
70
+ const PARTITION_COLORS = [
71
+ "#00ffff",
72
+ "#ffff00",
73
+ "#7fff00",
74
+ "#ff0000",
75
+ "#0000ff",
76
+ "#ffd8f2",
77
+ "#ffffff",
78
+ "#ff6321",
79
+ "#8c23ff",
80
+ "#606dc4",
81
+ "#1ef9a3",
82
+ "#009900",
83
+ "#7f7f7f",
84
+ "#000000",
85
+ "#ad0000",
86
+ "#ccffb2",
87
+ "#ffff99",
88
+ "#ff00ff",
89
+ "#007091",
90
+ "#ffb528",
91
+ "#ff0a9b",
92
+ "#00e000",
93
+ "#ff779e",
94
+ "#d8f2ff",
95
+ "#d8ff4f",
96
+ "#ff84ff",
97
+ "#e5ffcc",
98
+ "#ccccff",
99
+ "#59ddff",
100
+ "#ffd9bc",
101
+ "#db9370",
102
+ "#ccffff",
103
+ "#d8d8d8",
104
+ "#666666",
105
+ "#a5a5a5",
106
+ "#3f3f3f",
107
+ "#e5e5e5",
108
+ "#262626",
109
+ "#bfbfbf",
110
+ "#595959"
111
+ ];
112
+ const VERTEX_SIZE = 20;
113
+ const VERTEX_FILL = "#ffd9bc";
114
+ const SIZE_OF_VERTICES = 8;
115
+ function objectValues(snapshot, kind, n) {
116
+ if (n < 1) {
117
+ return null;
118
+ }
119
+ const pajek = snapshot.meta.extra.pajek;
120
+ const name = pajek?.objects?.filter((o) => o.kind === kind)[n - 1]?.column;
121
+ if (name === void 0 || !snapshot.nodes.has(name)) {
122
+ return null;
123
+ }
124
+ return (i) => {
125
+ const v = snapshot.nodes.value(name, i);
126
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
127
+ };
128
+ }
129
+ function column(values, property, n) {
130
+ values[property] ??= new Array(n).fill(null);
131
+ return values[property];
132
+ }
133
+ function drawVertices(draw, snapshot, node) {
134
+ const n = snapshot.nodeCount;
135
+ const width = column(node, "width", n);
136
+ const height = column(node, "height", n);
137
+ scaleVertexSizes(draw, width, height);
138
+ sizeByVectors(draw, snapshot, width, height);
139
+ colorByPartition(draw, snapshot, node);
140
+ const opacity = iniNumber(draw, "TransparencyofVertices");
141
+ if (opacity !== null && opacity < 1) {
142
+ const o = Math.max(0, opacity);
143
+ const fill = column(node, "fillOpacity", n);
144
+ fill.forEach((v, i) => {
145
+ fill[i] = (typeof v === "number" ? v : 1) * o;
146
+ });
147
+ column(node, "borderOpacity", n).fill(o * o);
148
+ }
149
+ if (flag(draw, "Form10.effect3d")) {
150
+ effect3d(snapshot, node);
151
+ }
152
+ markVertices(draw, node, n);
153
+ for (const property of ["width", "height"]) {
154
+ if (node[property].every((v) => v === null)) {
155
+ Reflect.deleteProperty(node, property);
156
+ }
157
+ }
158
+ }
159
+ function scaleVertexSizes(draw, width, height) {
160
+ const size = iniNumber(draw, "Form8.SizeofVertices");
161
+ if (size === null || size === SIZE_OF_VERTICES) {
162
+ return;
163
+ }
164
+ const f = size / SIZE_OF_VERTICES;
165
+ const scaled = (v) => typeof v === "number" ? v * f : VERTEX_SIZE * f * f;
166
+ for (let i = 0; i < width.length; i++) {
167
+ width[i] = scaled(width[i]);
168
+ height[i] = scaled(height[i]);
169
+ }
170
+ }
171
+ function colorByPartition(draw, snapshot, node) {
172
+ const partition = objectValues(snapshot, "partition", draw.partition);
173
+ if (partition === null) {
174
+ return;
175
+ }
176
+ const fill = column(node, "fill", snapshot.nodeCount);
177
+ for (let i = 0; i < snapshot.nodeCount; i++) {
178
+ const k = partition(i);
179
+ if (k !== null) {
180
+ fill[i] = PARTITION_COLORS[Math.abs(k) % PARTITION_COLORS.length];
181
+ }
182
+ }
183
+ }
184
+ function markVertices(draw, node, n) {
185
+ const mark = iniNumber(draw, "Form8.MarkVerticesUsing");
186
+ if (mark === 2) {
187
+ column(node, "label", n).forEach((_, i, a) => {
188
+ a[i] = String(i + 1);
189
+ });
190
+ } else if (mark === 3 || mark === 4) {
191
+ column(node, "label", n).fill("");
192
+ }
193
+ }
194
+ function effect3d(snapshot, node) {
195
+ const n = snapshot.nodeCount;
196
+ const fill = column(node, "fill", n);
197
+ const end = column(node, "fillGradient", n);
198
+ const angle = column(node, "fillGradientAngle", n);
199
+ const half = (v) => {
200
+ const h = v / 2;
201
+ const f = Math.floor(h);
202
+ return h - f === 0.5 && f % 2 === 0 ? f : Math.round(h);
203
+ };
204
+ for (let i = 0; i < n; i++) {
205
+ const color = typeof fill[i] === "string" ? String(fill[i]) : VERTEX_FILL;
206
+ end[i] = `#${[1, 3, 5].map(
207
+ (k) => half(Number.parseInt(color.slice(k, k + 2), 16)).toString(16).padStart(2, "0")
208
+ ).join("")}`;
209
+ const phi = snapshot.nodes.has("phi") ? Number(snapshot.nodes.value("phi", i)) : 0;
210
+ angle[i] = Number.isFinite(phi) ? ((90 - phi) % 360 + 360) % 360 : 90;
211
+ }
212
+ }
213
+ function sizeByVectors(draw, snapshot, width, height) {
214
+ const first = objectValues(snapshot, "vector", draw.vector);
215
+ if (first === null) {
216
+ return;
217
+ }
218
+ const second = objectValues(snapshot, "vector", draw.vector2);
219
+ const scale = (sizes, i, v) => {
220
+ if (v !== null && v >= 0) {
221
+ sizes[i] = (typeof sizes[i] === "number" ? sizes[i] : VERTEX_SIZE) * v;
222
+ }
223
+ };
224
+ for (let i = 0; i < snapshot.nodeCount; i++) {
225
+ const v = first(i);
226
+ if (second === null) {
227
+ const root = v === null || v < 0 ? null : Math.sqrt(v);
228
+ scale(width, i, root);
229
+ scale(height, i, root);
230
+ } else {
231
+ scale(width, i, v);
232
+ scale(height, i, second(i));
233
+ }
234
+ }
235
+ }
236
+ function drawLines(draw, snapshot, node, edge) {
237
+ const m = snapshot.edgeCount;
238
+ const opacity = iniNumber(draw, "TransparencyofLines");
239
+ if (opacity !== null && opacity < 1) {
240
+ const o = column(edge, "opacity", m);
241
+ o.forEach((v, e) => {
242
+ o[e] = (typeof v === "number" ? v : 1) * Math.max(0, opacity);
243
+ });
244
+ }
245
+ if (flag(draw, "Form10.StraightLinesOnly1")) {
246
+ const curved = column(edge, "curved", m);
247
+ for (let e = 0; e < m; e++) {
248
+ const bends = edge.bends?.[e];
249
+ if (bends === null || bends === void 0) {
250
+ curved[e] = false;
251
+ }
252
+ }
253
+ }
254
+ if (flag(draw, "Form10.ColorGradientLines")) {
255
+ const fill = node.fill;
256
+ const fillOf = (i) => typeof fill?.[i] === "string" ? fill[i] : VERTEX_FILL;
257
+ const colors = column(edge, "gradientColors", m);
258
+ const kind = column(edge, "gradientKind", m);
259
+ const sourceArrow = column(edge, "sourceArrowColor", m);
260
+ const targetArrow = column(edge, "targetArrowColor", m);
261
+ for (let e = 0; e < m; e++) {
262
+ const [s, t] = [fillOf(snapshot.edgeSource(e)), fillOf(snapshot.edgeTarget(e))];
263
+ colors[e] = `${s} ${t}`;
264
+ kind[e] = "linear";
265
+ sourceArrow[e] = s;
266
+ targetArrow[e] = t;
267
+ }
268
+ }
269
+ }
13
270
  const LABEL_COLUMN = "label";
14
271
  const POSITION_COLUMN = "position";
15
272
  const SHAPE_COLUMN = "shape";
@@ -256,7 +513,7 @@ function parseIntervals(token) {
256
513
  return [];
257
514
  }
258
515
  const spells = [];
259
- for (const part of body.split(",")) {
516
+ for (const part of body.split(/[,/]/)) {
260
517
  spells.push(parseSpell(token, part));
261
518
  }
262
519
  return spells;
@@ -328,6 +585,20 @@ function isParameterKey(text) {
328
585
  }
329
586
  return !/^[+-]?(\.\d|\d)/.test(text) && !/^[+-]?(?:nan|inf|infinity)$/i.test(text);
330
587
  }
588
+ const VOIDING_KEYS = /* @__PURE__ */ new Set([
589
+ "bc",
590
+ "bw",
591
+ "s_size",
592
+ "phi",
593
+ "r",
594
+ "q",
595
+ "lc",
596
+ "la",
597
+ "lr",
598
+ "lphi",
599
+ "fos",
600
+ "font"
601
+ ]);
331
602
  const PAJEK_STYLE_CAPABILITIES = Object.freeze({
332
603
  tool: "pajek",
333
604
  node: Object.freeze([
@@ -338,22 +609,95 @@ const PAJEK_STYLE_CAPABILITIES = Object.freeze({
338
609
  "borderColor",
339
610
  "borderWidth",
340
611
  "shape",
612
+ "shapePoints",
341
613
  "width",
342
614
  "height",
343
615
  "labelColor",
344
- "labelSize"
616
+ "labelSize",
617
+ "labelFont",
618
+ "labelPosition",
619
+ "labelOffsetX",
620
+ "labelOffsetY",
621
+ "labelShiftX"
622
+ ]),
623
+ edge: Object.freeze([
624
+ "color",
625
+ "opacity",
626
+ "width",
627
+ "lineStyle",
628
+ "sourceArrow",
629
+ "targetArrow",
630
+ "arrowSize",
631
+ "arrowPosition",
632
+ "label",
633
+ "labelColor",
634
+ "labelSize",
635
+ "labelFont"
345
636
  ]),
346
- edge: Object.freeze(["color", "opacity", "width", "lineStyle", "sourceArrow", "targetArrow"]),
347
637
  block: "native"
348
638
  });
349
- const VERTEX_SIZE = 5;
350
- const NODE_KEYS = ["ic", "bc", "bw", "x_fact", "y_fact", "lc", "fos"];
351
- const EDGE_KEYS = ["c", "w", "p"];
639
+ const PAJEK_VERTEX_SIZE = 20;
640
+ const PAJEK_FIGURES = /* @__PURE__ */ new Map([
641
+ ["other:man", [2.502, 6.487]],
642
+ ["other:woman", [3.003, 6.478]]
643
+ ]);
644
+ const PAJEK_FIGURE_UNSET_FACTOR = 0.3;
645
+ const PAJEK_POINTS_PER_UNIT = 500;
646
+ const NODE_KEYS = [
647
+ "ic",
648
+ "bc",
649
+ "bw",
650
+ "s_size",
651
+ "x_fact",
652
+ "y_fact",
653
+ "phi",
654
+ "q",
655
+ "lc",
656
+ "fos",
657
+ "font",
658
+ "lr",
659
+ "lphi",
660
+ "la"
661
+ ];
662
+ const EDGE_KEYS = ["c", "w", "p", "s", "ap", "l", "lc", "fos", "font"];
663
+ const CARRIED = {
664
+ node: [SHAPE_COLUMN, ...NODE_KEYS],
665
+ edge: ["c", "w", "p", "s", "ap"]
666
+ };
667
+ const CARRIED_LINE = CARRIED.edge.filter((key) => key !== "p" && key !== "ap");
668
+ const EDGE_WIDTH_PER_W = 2;
669
+ const ARC_DEFAULTS = { color: "#999999", width: 1 };
670
+ function carriedParams(keys, whole) {
671
+ let last = /* @__PURE__ */ new Map();
672
+ return (get) => {
673
+ const own = /* @__PURE__ */ new Map();
674
+ for (const key of keys) {
675
+ const v = get(key);
676
+ if (v !== null) {
677
+ own.set(key, v);
678
+ }
679
+ }
680
+ if (whole) {
681
+ if (own.size > 0) {
682
+ last = own;
683
+ return get;
684
+ }
685
+ } else {
686
+ for (const [key, v] of own) {
687
+ last.set(key, v);
688
+ }
689
+ }
690
+ const carried = last;
691
+ return (key) => get(key) ?? (keys.includes(key) ? carried.get(key) ?? null : null);
692
+ };
693
+ }
352
694
  const DIRECTED_KEY = "directed";
353
695
  const READ = {
354
696
  node: [
355
697
  "label",
356
698
  "shape",
699
+ "shapePoints",
700
+ "shapePointsStretch",
357
701
  "fill",
358
702
  "fillOpacity",
359
703
  "borderColor",
@@ -361,9 +705,26 @@ const READ = {
361
705
  "width",
362
706
  "height",
363
707
  "labelColor",
364
- "labelSize"
708
+ "labelSize",
709
+ "labelFont",
710
+ "labelPosition",
711
+ "labelOffsetX",
712
+ "labelOffsetY",
713
+ "labelShiftX",
714
+ "labelRotation"
365
715
  ],
366
- edge: ["color", "opacity", "width", "lineStyle"]
716
+ edge: [
717
+ "color",
718
+ "opacity",
719
+ "width",
720
+ "lineStyle",
721
+ "arrowSize",
722
+ "arrowPosition",
723
+ "label",
724
+ "labelColor",
725
+ "labelSize",
726
+ "labelFont"
727
+ ]
367
728
  };
368
729
  function readColor(raw, property, opacity, put, at) {
369
730
  if (raw === null) {
@@ -371,6 +732,10 @@ function readColor(raw, property, opacity, put, at) {
371
732
  }
372
733
  const c = canonColor(raw, "dvips", at(property));
373
734
  if (c === null) {
735
+ const unknown = UNKNOWN_COLORS.get(property);
736
+ if (unknown !== void 0 && typeof raw === "string" && /^[A-Za-z]\w*$/.test(raw.trim())) {
737
+ put(property, unknown);
738
+ }
374
739
  return;
375
740
  }
376
741
  put(property, c.color);
@@ -379,43 +744,454 @@ function readColor(raw, property, opacity, put, at) {
379
744
  put(opacity, alpha);
380
745
  }
381
746
  }
747
+ const UNKNOWN_COLORS = /* @__PURE__ */ new Map([
748
+ ["fill", "#ffffff"],
749
+ ["color", "#000000"]
750
+ ]);
382
751
  function readNumber(raw, property, put, at) {
383
752
  if (raw !== null) {
384
753
  put(property, canonNumber(raw, at(property)));
385
754
  }
386
755
  }
387
- function readVertex(get, put, at) {
756
+ function readVertex(get, put, at, place = null) {
388
757
  const label = get(LABEL_COLUMN);
389
758
  if (label !== null && label !== "") {
390
759
  put("label", canonText(label, at("label")));
391
760
  }
392
- const shape = get(SHAPE_COLUMN);
393
- if (shape !== null) {
394
- put("shape", canonEnum("shape", shape, "dvips", at("shape")));
761
+ const raw = get(SHAPE_COLUMN);
762
+ const shape = raw === null ? null : canonEnum("shape", raw, "dvips", at("shape"));
763
+ if (raw !== null) {
764
+ put("shape", shape);
395
765
  }
396
766
  readColor(get("ic"), "fill", "fillOpacity", put, at);
397
767
  readColor(get("bc"), "borderColor", null, put, at);
398
- const bw = get("bw");
399
- if (bw !== null) {
400
- const width = canonNumber(bw, at("borderWidth"));
401
- put("borderWidth", width === null ? null : width / VERTEX_SIZE);
402
- }
403
- readNumber(get("x_fact"), "width", put, at);
404
- readNumber(get("y_fact"), "height", put, at);
768
+ readNumber(get("bw"), "borderWidth", put, at);
769
+ readSize(get, put, at, PAJEK_FIGURES.get(String(shape)));
770
+ readOutline(get, put, shape);
405
771
  readColor(get("lc"), "labelColor", null, put, at);
406
772
  readNumber(get("fos"), "labelSize", put, at);
773
+ readFont(get("font"), put, at);
774
+ readLabelPosition(get, put, at);
775
+ readLabelAngle(get("la"), put, at, place);
776
+ if (shape === "none") {
777
+ for (const [property, value] of EMPTY_LABEL) {
778
+ put(property, value);
779
+ }
780
+ }
781
+ }
782
+ const PAJEK_OUTLINES = /* @__PURE__ */ new Map([
783
+ [
784
+ "rectangle",
785
+ [
786
+ [-1, 1],
787
+ [1, 1],
788
+ [1, -1],
789
+ [-1, -1]
790
+ ]
791
+ ],
792
+ [
793
+ "triangle",
794
+ [
795
+ [1, -1],
796
+ [0, 1],
797
+ [-1, -1]
798
+ ]
799
+ ],
800
+ [
801
+ "other:house",
802
+ [
803
+ [-0.7, -1],
804
+ [0.7, -1],
805
+ [0.7, 0.3],
806
+ [1, 0.3],
807
+ [1, 0.4],
808
+ [0, 1],
809
+ [-1, 0.4],
810
+ [-1, 0.3],
811
+ [-0.7, 0.3]
812
+ ]
813
+ ]
814
+ ]);
815
+ const PAJEK_DIAMOND_Q = 1e-3;
816
+ function readOutline(get, put, shape) {
817
+ const phi = numberOrNull(get("phi")) ?? 0;
818
+ const q = numberOrNull(get("q")) ?? PAJEK_DIAMOND_Q;
819
+ const diamond = [
820
+ [-1, 0],
821
+ [-q, 1],
822
+ [q, 1],
823
+ [1, 0],
824
+ [q, -1],
825
+ [-q, -1]
826
+ ];
827
+ const corners = shape === "diamond" ? diamond : PAJEK_OUTLINES.get(String(shape));
828
+ if (corners === void 0 || shape !== "diamond" && phi % 360 === 0) {
829
+ return;
830
+ }
831
+ const [w, h] = [numberOrNull(get("x_fact")) || 1, numberOrNull(get("y_fact")) || 1];
832
+ const [c, s] = [Math.cos(phi * Math.PI / 180), Math.sin(phi * Math.PI / 180)];
833
+ const round = (v) => String(Number(v.toFixed(4)) + 0);
834
+ const points = corners.map(([x, y]) => {
835
+ const [px, py] = [x * w, y * h];
836
+ return `${round((px * c - py * s) / w)},${round((px * s + py * c) / h)}`;
837
+ });
838
+ put("shape", "polygon");
839
+ put("shapePoints", points.join(" "));
840
+ put("shapePointsStretch", false);
841
+ }
842
+ const EMPTY_LABEL = [
843
+ ["labelSize", 1],
844
+ ["labelColor", "#ffffff"],
845
+ ["labelPosition", "center"],
846
+ ["labelOffsetX", 0],
847
+ ["labelOffsetY", 0],
848
+ ["labelShiftX", 0]
849
+ ];
850
+ function readFont(raw, put, at) {
851
+ if (raw === null || raw === "") {
852
+ return;
853
+ }
854
+ const ps = typeof raw === "string" ? postscriptFont(raw.trim()) : null;
855
+ if (ps === null) {
856
+ readText(raw, "labelFont", put, at);
857
+ return;
858
+ }
859
+ put("labelFont", ps.family);
860
+ }
861
+ function readLabelAngle(raw, put, at, place) {
862
+ let a = raw === null ? null : canonNumber(raw, at("labelRotation"));
863
+ if (a !== null && a >= 360) {
864
+ a = place === null ? null : Math.atan2(0.5 - place[1], place[0] - 0.5) * 180 / Math.PI + a - 360;
865
+ }
866
+ if (a !== null) {
867
+ put("labelRotation", Number((((360 - a) % 360 + 360) % 360).toPrecision(12)));
868
+ }
869
+ }
870
+ function readSize(get, put, at, figure) {
871
+ for (const [key, property, k] of [
872
+ ["x_fact", "width", 0],
873
+ ["y_fact", "height", 1]
874
+ ]) {
875
+ const f = get(key);
876
+ if (f === null && figure === void 0) {
877
+ continue;
878
+ }
879
+ const unset = figure === void 0 ? 1 : PAJEK_FIGURE_UNSET_FACTOR;
880
+ const factor = f === null ? unset : canonNumber(f, at(property));
881
+ const over = figure?.[k] ?? 1;
882
+ put(property, factor === null ? null : Number((PAJEK_VERTEX_SIZE * factor * over).toPrecision(15)));
883
+ }
884
+ }
885
+ function readText(raw, property, put, at) {
886
+ if (raw !== null && raw !== "") {
887
+ put(property, canonText(raw, at(property)));
888
+ }
889
+ }
890
+ const SIDE_ANGLES = /* @__PURE__ */ new Map([
891
+ ["right", 0],
892
+ ["top-right", 90],
893
+ ["left", 180],
894
+ ["bottom-right", 285]
895
+ ]);
896
+ const NEAREST_SIDES = /* @__PURE__ */ new Map([
897
+ ["top", "top-right"],
898
+ ["top-left", "top-right"],
899
+ ["bottom", "bottom-right"],
900
+ ["bottom-left", "bottom-right"]
901
+ ]);
902
+ function readLabelPosition(get, put, at) {
903
+ const [lr, lphi, fos] = [get("lr"), get("lphi"), get("fos")];
904
+ if (lr === null && lphi === null && fos === null) {
905
+ return;
906
+ }
907
+ const radius = lr === null ? PAJEK_LABEL_RADIUS : canonNumber(lr, at("labelPosition"));
908
+ const angle = lphi === null ? PAJEK_LABEL_ANGLE : canonNumber(lphi, at("labelPosition"));
909
+ const size = fos === null ? PAJEK_LABEL_SIZE : canonNumber(fos, at("labelSize"));
910
+ if (radius === null || angle === null || size === null) {
911
+ return;
912
+ }
913
+ const [x, y] = labelOffset(radius, angle, size);
914
+ put("labelPosition", "center");
915
+ put("labelOffsetX", x);
916
+ put("labelOffsetY", y);
917
+ put("labelShiftX", radius === 0 ? 0 : 0.5);
918
+ }
919
+ function labelOffset(radius, angle, size) {
920
+ if (radius === 0) {
921
+ return [0, 0];
922
+ }
923
+ const t = angle * Math.PI / 180;
924
+ const round = (v) => Number(v.toFixed(9)) + 0;
925
+ return [round(radius * Math.cos(t)), round(-radius * Math.sin(t) - PAJEK_BASELINE_TO_MIDDLE * size)];
407
926
  }
408
- function readLine(get, put, at) {
927
+ const PAJEK_LABEL_RADIUS = 20;
928
+ const PAJEK_LABEL_ANGLE = 285;
929
+ const PAJEK_LABEL_SIZE = 15;
930
+ const PAJEK_BASELINE_TO_MIDDLE = 0.3465;
931
+ function readLine(get, put, at, directed, labels = true, run = null, loop = null) {
409
932
  readColor(get("c"), "color", "opacity", put, at);
410
- readNumber(get("w"), "width", put, at);
933
+ readNumber(
934
+ get("w"),
935
+ "width",
936
+ (property, value) => {
937
+ put(property, typeof value === "number" && !directed ? value * EDGE_WIDTH_PER_W : value);
938
+ },
939
+ at
940
+ );
411
941
  const p = get("p");
412
- if (p !== null) {
413
- put("lineStyle", canonEnum("lineStyle", p, "dvips", at("lineStyle")));
942
+ if (p === "Dots") {
943
+ put("lineStyle", pajekDash(get, directed));
944
+ } else if (p === "Solid") {
945
+ put("lineStyle", "solid");
946
+ } else if (p !== null) {
947
+ noteAt(at("lineStyle"), STYLE_ISSUE.UNKNOWN_VALUE, typeof p === "string" ? p : JSON.stringify(p));
948
+ put("lineStyle", "solid");
949
+ }
950
+ readNumber(get("s"), "arrowSize", put, at);
951
+ readArrowPosition(get("ap"), put, at, run);
952
+ const line = loop === null ? get : loopParam(get);
953
+ const controls = loop === null ? null : readLoop(line, put, loop);
954
+ if (labels) {
955
+ readText(get("l"), "label", put, at);
956
+ if (controls === null) {
957
+ readLineLabelPlace(get, put, at, run);
958
+ } else {
959
+ readLineLabelPlace(line, put, at, [PAJEK_POINTS_PER_UNIT, 0], loopTop(controls));
960
+ }
961
+ }
962
+ if (loop === null) {
963
+ readBezier(get, put, run);
964
+ }
965
+ readColor(get("lc"), "labelColor", null, put, at);
966
+ readNumber(get("fos"), "labelSize", put, at);
967
+ readFont(get("font"), put, at);
968
+ }
969
+ const LOOP_DEFAULTS = { a1: -70, k1: 0.3, a2: -70, k2: 0.3 };
970
+ function loopParam(get) {
971
+ return (key) => get(key) ?? (key in LOOP_DEFAULTS ? LOOP_DEFAULTS[key] : null);
972
+ }
973
+ function readLoop(get, put, loop) {
974
+ const run = [PAJEK_POINTS_PER_UNIT, 0];
975
+ const controls = bezierControls(get, run);
976
+ if (controls === null) {
977
+ return null;
978
+ }
979
+ const [[a1, l1], [a2, l2]] = controls;
980
+ const L = PAJEK_POINTS_PER_UNIT;
981
+ const [c1, c2] = [
982
+ [a1 * L, -l1 * L],
983
+ [(a2 - 1) * L, -l2 * L]
984
+ ];
985
+ loop([c1, c2]);
986
+ put("curved", true);
987
+ put("bendCurve", "bezier");
988
+ put("targetArrow", "none");
989
+ return [c1, c2];
990
+ }
991
+ function loopTop(controls) {
992
+ const [c1, c2] = controls;
993
+ return Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI;
994
+ }
995
+ function layLoops(snapshot, loops, node, edge) {
996
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
997
+ for (const [e, controls] of loops) {
998
+ const v = snapshot.edgeSource(e);
999
+ const half = (property) => {
1000
+ const size = node[property]?.[v];
1001
+ return (typeof size === "number" && size > 0 ? size : PAJEK_VERTEX_SIZE) / 2;
1002
+ };
1003
+ const [hw, hh] = [half("width"), half("height")];
1004
+ const column2 = (property) => edge[property] ??= new Array(snapshot.edgeCount).fill(null);
1005
+ column2("bends")[e] = controls.map(([x, y]) => `${fraction(x / hw)},${fraction(-y / hh)}`).join(" ");
1006
+ column2("curved")[e] = true;
1007
+ column2("bendCurve")[e] = "bezier";
1008
+ }
1009
+ }
1010
+ function readLineLabelPlace(get, put, at, run, direction) {
1011
+ const length = run === null ? 0 : Math.hypot(run[0], run[1]);
1012
+ if (run === null || length === 0) {
1013
+ return;
1014
+ }
1015
+ const n = (key, fallback, property) => {
1016
+ const v = get(key);
1017
+ return v === null ? fallback : canonNumber(v, at(property));
1018
+ };
1019
+ const [lp, lr, lphi, la] = [
1020
+ n("lp", 0.5, "labelOffsetX"),
1021
+ n("lr", 0, "labelOffsetX"),
1022
+ n("lphi", 0, "labelOffsetX"),
1023
+ n("la", 0, "labelRotation")
1024
+ ];
1025
+ const size = n("fos", PAJEK_LABEL_SIZE, "labelSize");
1026
+ if (lp === null || lr === null || lphi === null || la === null || size === null) {
1027
+ return;
1028
+ }
1029
+ const along = 0.5 - (lp <= 1 ? lp : lp / length);
1030
+ const t = lphi * Math.PI / 180;
1031
+ const round = (v) => Number(v.toFixed(9)) + 0;
1032
+ const turn = ((direction ?? lineDirection(get, run, along + 0.5)) - la) % 360 + 360;
1033
+ const up = turn * Math.PI / 180;
1034
+ const rise = PAJEK_BASELINE_TO_MIDDLE * size;
1035
+ put("labelPosition", "center");
1036
+ put("labelOffsetX", round(along * run[0] + lr * Math.cos(t) + rise * Math.sin(up)));
1037
+ put("labelOffsetY", round(along * run[1] - lr * Math.sin(t) - rise * Math.cos(up)));
1038
+ put("labelRotation", round(turn % 360));
1039
+ }
1040
+ function readBezier(get, put, run) {
1041
+ const controls = bezierControls(get, run);
1042
+ if (controls === null) {
1043
+ return;
1044
+ }
1045
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
1046
+ put("curved", true);
1047
+ put("bendCurve", "bezier");
1048
+ put("bends", controls.map(([along, across]) => `${fraction(along)},${fraction(across)}`).join(" "));
1049
+ }
1050
+ const PAJEK_TIP_BACK = 1.5;
1051
+ function readArcEnd(get, put, run, target) {
1052
+ const ap = numberOrNull(get("ap")) ?? 0;
1053
+ const length = Math.hypot(run[0], run[1]);
1054
+ if (ap !== 0 || length === 0 || bezierControls(get, run) === null) {
1055
+ return false;
1056
+ }
1057
+ const [ux, uy] = [run[0] / length, run[1] / length];
1058
+ const r = 1 / Math.hypot(ux / (target[0] / 2), uy / (target[1] / 2));
1059
+ const back = PAJEK_TIP_BACK + 5 * (numberOrNull(get("s")) ?? 1);
1060
+ const turn = -(numberOrNull(get("a2")) ?? 0) * Math.PI / 180;
1061
+ const [c, s] = [Math.cos(turn), Math.sin(turn)];
1062
+ const end = [run[0] - r * ux - back * (ux * c - uy * s), run[1] - r * uy - back * (ux * s + uy * c)];
1063
+ const controls = bezierControls(get, end);
1064
+ if (controls === null) {
1065
+ return false;
1066
+ }
1067
+ const L2 = length * length;
1068
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
1069
+ const bends = controls.map(([along, left]) => {
1070
+ const [x, y] = [along * end[0] + left * end[1], along * end[1] - left * end[0]];
1071
+ return `${fraction((x * run[0] + y * run[1]) / L2)},${fraction((x * run[1] - y * run[0]) / L2)}`;
1072
+ });
1073
+ put("bends", bends.join(" "));
1074
+ const tip = [-r * ux - PAJEK_TIP_BACK * (ux * c - uy * s), -r * uy - PAJEK_TIP_BACK * (ux * s + uy * c)];
1075
+ put("targetPort", `${fraction(tip[0] / (target[0] / 2))},${fraction(-tip[1] / (target[1] / 2))}`);
1076
+ return true;
1077
+ }
1078
+ const PAJEK_TIP_GAP = 1;
1079
+ function readTipGap(get, put) {
1080
+ const s = numberOrNull(get("s")) ?? 1;
1081
+ if (s > 0) {
1082
+ put("targetArrowGap", Number((PAJEK_TIP_GAP / (6 * s)).toPrecision(6)));
1083
+ }
1084
+ }
1085
+ function bezierControls(get, run) {
1086
+ const [a1, k1, a2, k2] = ["a1", "k1", "a2", "k2"].map((key) => numberOrNull(get(key)));
1087
+ if (a1 === null && k1 === null && a2 === null && k2 === null || run === null || run[0] === 0 && run[1] === 0) {
1088
+ return null;
1089
+ }
1090
+ const [s, t] = [k1 ?? 1, k2 ?? 1];
1091
+ if (s < 0 || t < 0) {
1092
+ return null;
1093
+ }
1094
+ const rad = Math.PI / 180;
1095
+ const [u, v] = [(a1 ?? 0) * rad, (a2 ?? 0) * rad];
1096
+ return [
1097
+ [s / 2 * Math.cos(u), -s / 2 * Math.sin(u)],
1098
+ [1 - t / 2 * Math.cos(v), -t / 2 * Math.sin(v)]
1099
+ ];
1100
+ }
1101
+ function lineDirection(get, run, along) {
1102
+ const controls = bezierControls(get, run);
1103
+ let [dx, dy] = run;
1104
+ if (controls !== null) {
1105
+ const t = Math.min(1, Math.max(0, along));
1106
+ const p = [[0, 0], ...controls, [1, 0]];
1107
+ const d = (k) => 3 * (1 - t) ** 2 * (p[1][k] - p[0][k]) + 6 * (1 - t) * t * (p[2][k] - p[1][k]) + 3 * t ** 2 * (p[3][k] - p[2][k]);
1108
+ const [a, l] = [d(0), d(1)];
1109
+ [dx, dy] = [a * run[0] + l * run[1], a * run[1] - l * run[0]];
1110
+ }
1111
+ return Math.atan2(dy, dx) * 180 / Math.PI;
1112
+ }
1113
+ function readLineValue(value, get, put, directed = true) {
1114
+ if (value === 0) {
1115
+ put("visible", false);
1116
+ } else if (value !== null && value < 0 && get("p") === null) {
1117
+ put("lineStyle", pajekDash(get, directed));
1118
+ }
1119
+ }
1120
+ const PAJEK_DASH = 5;
1121
+ function pajekDash(get, directed) {
1122
+ const w = numberOrNull(get("w"));
1123
+ const width = (w ?? 1) * (directed ? 1 : EDGE_WIDTH_PER_W);
1124
+ return PAJEK_DASH <= 1.5 * Math.max(1, width) ? "dotted" : "dashed";
1125
+ }
1126
+ function readHooks(get, put, source, target) {
1127
+ for (const [key, property, shape] of [
1128
+ ["h1", "sourcePort", source],
1129
+ ["h2", "targetPort", target]
1130
+ ]) {
1131
+ const hook = numberOrNull(get(key));
1132
+ const port = hook === null ? null : hookPort(shape, hook);
1133
+ if (port !== null) {
1134
+ const round = (v) => String(Number(v.toFixed(4)) + 0);
1135
+ put(property, `${round(port[0])},${round(port[1])}`);
1136
+ }
1137
+ }
1138
+ }
1139
+ function hookPort(shape, hook) {
1140
+ if (!Number.isInteger(hook) || hook < 1) {
1141
+ return null;
1142
+ }
1143
+ const keyword = typeof shape === "string" ? shape.toLowerCase() : "ellipse";
1144
+ if (keyword === "ellipse" || keyword === "cross") {
1145
+ const a = hook * Math.PI / 180;
1146
+ return [Math.cos(a), Math.sin(a)];
1147
+ }
1148
+ if (keyword !== "box" || hook > 400) {
1149
+ return null;
1150
+ }
1151
+ const d = hook * 0.02;
1152
+ if (hook <= 50) {
1153
+ return [1, d];
1154
+ }
1155
+ if (hook <= 150) {
1156
+ return [2 - d, 1];
1157
+ }
1158
+ if (hook <= 250) {
1159
+ return [-1, 4 - d];
1160
+ }
1161
+ return hook <= 350 ? [d - 6, -1] : [1, d - 8];
1162
+ }
1163
+ function numberOrNull(raw) {
1164
+ if (typeof raw === "string" && raw.trim() !== "") {
1165
+ raw = Number(raw);
1166
+ }
1167
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
1168
+ }
1169
+ function readArrowPosition(raw, put, at, run = null) {
1170
+ if (raw === null) {
1171
+ return;
1172
+ }
1173
+ const ap = canonNumber(raw, at("arrowPosition"));
1174
+ const length = run === null ? 0 : Math.hypot(run[0], run[1]);
1175
+ if (ap !== null && ap > 1) {
1176
+ if (length > 0) {
1177
+ put("arrowPosition", Number(Math.min(1, ap / length).toPrecision(6)));
1178
+ } else {
1179
+ noteAt(at("arrowPosition"), STYLE_ISSUE.NOT_CARRIED, `ap ${String(ap)}`);
1180
+ }
1181
+ return;
1182
+ }
1183
+ if (ap !== 0) {
1184
+ put("arrowPosition", ap);
414
1185
  }
415
1186
  }
416
1187
  function cells(table, i) {
417
- return (key) => table.has(key) ? plainCell(table.value(key, i)) : null;
1188
+ return (key) => {
1189
+ const v = table.has(key) ? plainCell(table.value(key, i)) : null;
1190
+ return COLOR_PARAMS.has(key) && typeof v === "string" && NUMERIC_COLOR.test(v) ? null : v;
1191
+ };
418
1192
  }
1193
+ const COLOR_PARAMS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
1194
+ const NUMERIC_COLOR = /^[\d.]+(?: [\d.]+)*$/;
419
1195
  function directedEdges(snapshot) {
420
1196
  const out = new Array(snapshot.edgeCount).fill(snapshot.directed);
421
1197
  const col = snapshot.directed ? snapshot.edges.byRole("directed") : null;
@@ -426,37 +1202,115 @@ function directedEdges(snapshot) {
426
1202
  }
427
1203
  return out;
428
1204
  }
1205
+ const SHARED_ARC_BOW = { a1: 15, k1: 0.25, a2: 15, k2: 0.25 };
1206
+ function sharedArcBows(snapshot, directed) {
1207
+ const byPair = /* @__PURE__ */ new Map();
1208
+ for (let e = 0; e < snapshot.edgeCount; e++) {
1209
+ const [u, v] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
1210
+ if (directed[e] && u !== v) {
1211
+ const key = u < v ? `${String(u)} ${String(v)}` : `${String(v)} ${String(u)}`;
1212
+ byPair.set(key, [...byPair.get(key) ?? [], e]);
1213
+ }
1214
+ }
1215
+ const out = /* @__PURE__ */ new Map();
1216
+ for (const arcs of byPair.values()) {
1217
+ if (arcs.length < 2) {
1218
+ continue;
1219
+ }
1220
+ for (const e of arcs) {
1221
+ const same = arcs.filter((x) => snapshot.edgeSource(x) === snapshot.edgeSource(e));
1222
+ out.set(e, (same.length - 1 - same.indexOf(e)) % 2 === 0 ? 1 : -1);
1223
+ }
1224
+ }
1225
+ return out;
1226
+ }
1227
+ function bowedParams(get, side) {
1228
+ if (Object.keys(SHARED_ARC_BOW).some((key) => get(key) !== null)) {
1229
+ return get;
1230
+ }
1231
+ return (key) => {
1232
+ const bow = SHARED_ARC_BOW[key];
1233
+ if (bow === void 0) {
1234
+ return get(key);
1235
+ }
1236
+ return key.startsWith("a") ? side * bow : bow;
1237
+ };
1238
+ }
429
1239
  function styleColumns(table, keys) {
430
1240
  return keys.filter((k) => table.has(k));
431
1241
  }
432
1242
  function pajekStyles(snapshot, context) {
433
1243
  const notes = new StyleNotes();
1244
+ const { block, draw, voided } = keptOf(context.kept);
1245
+ const labels = drawsLineLabels(draw);
1246
+ const place = places(snapshot);
1247
+ const window = draw ?? { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
1248
+ const loops = /* @__PURE__ */ new Map();
1249
+ const runOf = (e) => {
1250
+ const [s, t] = [place(snapshot.edgeSource(e)), place(snapshot.edgeTarget(e))];
1251
+ return s === null || t === null ? null : [(t[0] - s[0]) * window.width, (t[1] - s[1]) * window.height];
1252
+ };
434
1253
  const read = (target) => {
435
1254
  const table = target === "node" ? snapshot.nodes : snapshot.edges;
436
1255
  const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
437
1256
  const out = valueColumns(n);
1257
+ const carry = carriedParams(target === "node" ? CARRIED.node : CARRIED_LINE, target === "node");
438
1258
  for (let i = 0; i < n; i++) {
439
1259
  context.budget.spend(target, 1);
440
1260
  const at = (property) => ({ notes, target, property, element: i, budget: context.budget });
441
- (target === "node" ? readVertex : readLine)(
442
- cells(table, i),
443
- (property, value) => {
444
- out.put(i, property, value);
445
- },
446
- at
447
- );
1261
+ const put = (property, value) => {
1262
+ out.put(i, property, value);
1263
+ };
1264
+ const own = cells(table, i);
1265
+ const get = target === "node" && voided.has(i) ? voidedParams(own, keywords[i - 1] ?? null) : carry(own);
1266
+ if (target === "node") {
1267
+ readVertex(get, put, at, place(i));
1268
+ keywords[i] = get(SHAPE_COLUMN);
1269
+ } else {
1270
+ readEdge(i, get, put, at);
1271
+ }
448
1272
  }
449
1273
  return out.values;
450
1274
  };
1275
+ const readEdge = (i, get, put, at) => {
1276
+ const run = runOf(i);
1277
+ const loop = run !== null && block === null && snapshot.edgeSource(i) === snapshot.edgeTarget(i) ? (controls) => {
1278
+ loops.set(i, controls);
1279
+ } : null;
1280
+ const bow = bows.get(i);
1281
+ const line = bow === void 0 ? get : bowedParams(get, bow);
1282
+ readLine(line, put, at, directed[i], labels, run, loop);
1283
+ const ported = directed[i] && run !== null && readArcEnd(line, put, run, targetSize(snapshot.edgeTarget(i)));
1284
+ if (directed[i] && loop === null && !ported && block === null) {
1285
+ readTipGap(get, put);
1286
+ }
1287
+ readLineValue(lineValue(i), get, put, directed[i]);
1288
+ readHooks(get, put, keywords[snapshot.edgeSource(i)], keywords[snapshot.edgeTarget(i)]);
1289
+ };
1290
+ const directed = directedEdges(snapshot);
1291
+ const bows = drawsStraightLines(draw) || block !== null ? /* @__PURE__ */ new Map() : sharedArcBows(snapshot, directed);
1292
+ const keywords = [];
1293
+ const weights = explicitWeights(snapshot);
1294
+ const lineValue = (e) => weights.isExplicit(e) ? weights.value(e) : numberOrNull(cells(snapshot.edges, e)(VALUE_COLUMN));
451
1295
  const node = read("node");
1296
+ const targetSize = (v) => {
1297
+ const size = (property) => {
1298
+ const s = node[property]?.[v];
1299
+ return typeof s === "number" && s > 0 ? s : PAJEK_VERTEX_SIZE;
1300
+ };
1301
+ return [size("width"), size("height")];
1302
+ };
452
1303
  const edge = read("edge");
453
- const block = typeof context.kept === "string" ? context.kept : null;
1304
+ if (draw !== null) {
1305
+ drawVertices(draw, snapshot, node);
1306
+ drawLines(draw, snapshot, node, edge);
1307
+ }
1308
+ layLoops(snapshot, loops, node, edge);
454
1309
  if (block !== null) {
455
- exactFromBlock(snapshot, block, { node, edge });
1310
+ exactFromBlock(snapshot, block, { node, edge }, labels);
456
1311
  }
457
1312
  const rules = [];
458
1313
  const columns = /* @__PURE__ */ new Map();
459
- const directed = directedEdges(snapshot);
460
1314
  if (directed.some(Boolean)) {
461
1315
  columns.set(
462
1316
  DIRECTED_KEY,
@@ -468,14 +1322,14 @@ function pajekStyles(snapshot, context) {
468
1322
  role: "group",
469
1323
  origin: "tool",
470
1324
  where: { has: { style: DIRECTED_KEY } },
471
- set: { targetArrow: "triangle" }
1325
+ set: { targetArrow: "triangle", color: ARC_DEFAULTS.color, width: ARC_DEFAULTS.width }
472
1326
  });
473
1327
  }
474
1328
  return {
475
1329
  canonical: true,
476
1330
  dialect: "dvips",
477
1331
  tool: "pajek",
478
- units: "relative",
1332
+ units: "px",
479
1333
  node: { values: node },
480
1334
  edge: { values: edge, rules, columns },
481
1335
  notes: notes.list(),
@@ -486,6 +1340,39 @@ function pajekStyles(snapshot, context) {
486
1340
  }
487
1341
  };
488
1342
  }
1343
+ function places(snapshot) {
1344
+ const col = snapshot.nodes.byRole("position");
1345
+ return (i) => {
1346
+ const v = col === null || col === void 0 ? null : col.value(i);
1347
+ if (v === null || typeof v !== "object" || !("length" in v)) {
1348
+ return null;
1349
+ }
1350
+ const [x, y] = v;
1351
+ return typeof x === "number" && typeof y === "number" ? [x, y] : null;
1352
+ };
1353
+ }
1354
+ function keptOf(kept) {
1355
+ if (typeof kept === "string") {
1356
+ return { block: kept, draw: null, voided: /* @__PURE__ */ new Set() };
1357
+ }
1358
+ if (typeof kept === "object" && kept !== null) {
1359
+ const { block, pajekDraw, voided } = kept;
1360
+ return {
1361
+ block: typeof block === "string" ? block : null,
1362
+ draw: pajekDraw ?? null,
1363
+ voided: new Set(voided ?? [])
1364
+ };
1365
+ }
1366
+ return { block: null, draw: null, voided: /* @__PURE__ */ new Set() };
1367
+ }
1368
+ function voidedParams(own, before) {
1369
+ return (key) => {
1370
+ if (key === LABEL_COLUMN) {
1371
+ return own(key);
1372
+ }
1373
+ return key === SHAPE_COLUMN ? before : null;
1374
+ };
1375
+ }
489
1376
  const SHAPES = /* @__PURE__ */ new Map([
490
1377
  ["ellipse", "ellipse"],
491
1378
  ["rectangle", "box"],
@@ -526,9 +1413,37 @@ function shapeKeyword(get, approximate) {
526
1413
  if (keyword !== void 0) {
527
1414
  return keyword;
528
1415
  }
1416
+ if (shape === "polygon" && diamondQ(get) !== null) {
1417
+ return "diamond";
1418
+ }
529
1419
  approximate("shape", shape);
1420
+ const points = get("shapePoints");
1421
+ if (shape === "polygon" && points !== null) {
1422
+ approximate("shapePoints", points);
1423
+ }
530
1424
  return NEAREST_SHAPES.get(shape) ?? "ellipse";
531
1425
  }
1426
+ function diamondQ(get) {
1427
+ const points = get("shapePoints");
1428
+ const corners = typeof points === "string" ? points.trim().split(/\s+/).map((p) => p.split(",").map(Number)) : [];
1429
+ if (corners.length !== 6) {
1430
+ return null;
1431
+ }
1432
+ const q = corners[2][0];
1433
+ const want = [
1434
+ [-1, 0],
1435
+ [-q, 1],
1436
+ [q, 1],
1437
+ [1, 0],
1438
+ [q, -1],
1439
+ [-q, -1]
1440
+ ];
1441
+ return want.every(([x, y], k) => corners[k][0] === x && corners[k][1] === y) ? q : null;
1442
+ }
1443
+ function pajekDefault(target, property) {
1444
+ const values = toolDefaults("pajek")?.[target];
1445
+ return values?.[property]?.value;
1446
+ }
532
1447
  function vertexParams(get, approximate) {
533
1448
  const out = /* @__PURE__ */ new Map();
534
1449
  opaque(get, ["fillOpacity", "opacity"], approximate);
@@ -536,54 +1451,114 @@ function vertexParams(get, approximate) {
536
1451
  if (keyword !== "ellipse") {
537
1452
  out.set(SHAPE_COLUMN, keyword);
538
1453
  }
1454
+ const q = diamondQ(get);
1455
+ if (q !== null && q !== PAJEK_DIAMOND_Q) {
1456
+ out.set("q", q);
1457
+ }
1458
+ vertexColorParams(get, out);
1459
+ vertexSizeParams(get, out);
1460
+ const bw = get("borderWidth");
1461
+ if (typeof bw === "number" && bw !== pajekDefault("node", "borderWidth")) {
1462
+ out.set("bw", bw);
1463
+ }
1464
+ fontParam(get, out, pajekDefault("node", "labelFont"));
1465
+ labelPositionParams(get, out, approximate);
1466
+ return out;
1467
+ }
1468
+ function vertexColorParams(get, out) {
539
1469
  const colors = [
540
1470
  ["fill", "ic"],
541
1471
  ["borderColor", "bc"],
542
1472
  ["labelColor", "lc"]
543
1473
  ];
544
- const numbers = [
545
- ["width", "x_fact"],
546
- ["height", "y_fact"],
547
- ["labelSize", "fos"]
548
- ];
549
1474
  for (const [property, key] of colors) {
550
1475
  const v = get(property);
551
- if (typeof v === "string" && (property === "fill" || v !== "#000000")) {
1476
+ if (typeof v === "string" && v !== pajekDefault("node", property)) {
552
1477
  out.set(key, pajekColorText(v));
553
1478
  }
554
1479
  }
555
- for (const [property, key] of numbers) {
1480
+ }
1481
+ function vertexSizeParams(get, out) {
1482
+ const numbers = [
1483
+ ["width", "x_fact", PAJEK_VERTEX_SIZE],
1484
+ ["height", "y_fact", PAJEK_VERTEX_SIZE],
1485
+ ["labelSize", "fos", 1]
1486
+ ];
1487
+ const figure = PAJEK_FIGURES.get(String(get("shape")));
1488
+ for (const [property, key, per] of numbers) {
556
1489
  const v = get(property);
557
- if (typeof v === "number") {
558
- out.set(key, v);
1490
+ let over = 1;
1491
+ if (figure !== void 0 && key !== "fos") {
1492
+ over = figure[key === "x_fact" ? 0 : 1];
1493
+ }
1494
+ if (typeof v === "number" && (over !== 1 || v !== pajekDefault("node", property))) {
1495
+ out.set(key, Number((v / (per * over)).toPrecision(15)));
559
1496
  }
560
1497
  }
561
- const bw = get("borderWidth");
562
- if (typeof bw === "number") {
563
- const written = Number((bw * VERTEX_SIZE).toPrecision(15));
564
- if (written === 1) {
565
- out.delete("bw");
566
- } else {
567
- out.set("bw", written);
1498
+ }
1499
+ function fontParam(get, out, skip) {
1500
+ const font = get("labelFont");
1501
+ const name = typeof font === "string" && font !== "" ? graphvizFontName(font, false, false) : null;
1502
+ if (name !== null && name !== skip) {
1503
+ out.set("font", name);
1504
+ }
1505
+ }
1506
+ function labelPositionParams(get, out, approximate) {
1507
+ const position = get("labelPosition");
1508
+ if (typeof position !== "string") {
1509
+ return;
1510
+ }
1511
+ if (position === "center") {
1512
+ const polar = polarOf(get);
1513
+ if (polar === null) {
1514
+ out.set("lr", 0);
1515
+ } else if (polar[0] !== PAJEK_LABEL_RADIUS || polar[1] !== PAJEK_LABEL_ANGLE) {
1516
+ out.set("lr", polar[0]);
1517
+ out.set("lphi", polar[1]);
568
1518
  }
1519
+ return;
569
1520
  }
570
- return out;
1521
+ const nearest = NEAREST_SIDES.get(position);
1522
+ if (nearest !== void 0) {
1523
+ approximate("labelPosition", position);
1524
+ }
1525
+ const angle = SIDE_ANGLES.get(nearest ?? position);
1526
+ if (angle !== void 0 && angle !== PAJEK_LABEL_ANGLE) {
1527
+ out.set("lphi", angle);
1528
+ }
1529
+ }
1530
+ function polarOf(get) {
1531
+ const [x, y, shift] = [get("labelOffsetX"), get("labelOffsetY"), get("labelShiftX")];
1532
+ if (typeof x !== "number" || typeof y !== "number" || shift !== 0.5) {
1533
+ return null;
1534
+ }
1535
+ const size = get("labelSize");
1536
+ const up = y + PAJEK_BASELINE_TO_MIDDLE * (typeof size === "number" ? size : PAJEK_LABEL_SIZE);
1537
+ const round = (v) => Number(v.toFixed(6)) + 0;
1538
+ const lr = round(Math.hypot(x, up));
1539
+ return lr === 0 ? null : [lr, round((Math.atan2(-up, x) * 180 / Math.PI % 360 + 360) % 360)];
1540
+ }
1541
+ function lineDefaults(directed) {
1542
+ return directed ? ARC_DEFAULTS : { color: pajekDefault("edge", "color"), width: pajekDefault("edge", "width") };
571
1543
  }
572
1544
  function lineParams(get, directed, approximate) {
573
1545
  const out = /* @__PURE__ */ new Map();
574
1546
  opaque(get, ["opacity"], approximate);
1547
+ const defaults = lineDefaults(directed);
575
1548
  const color = get("color");
576
- if (typeof color === "string" && color !== "#000000") {
1549
+ if (typeof color === "string" && color !== defaults.color) {
577
1550
  out.set("c", pajekColorText(color));
578
1551
  }
579
1552
  const width = get("width");
580
- if (typeof width === "number") {
581
- out.set("w", width);
1553
+ if (typeof width === "number" && width !== defaults.width) {
1554
+ out.set("w", directed ? width : Number((width / EDGE_WIDTH_PER_W).toPrecision(15)));
582
1555
  }
583
1556
  const lineStyle = get("lineStyle");
584
- if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, approximate)) {
1557
+ if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, out, directed, approximate)) {
585
1558
  out.set("p", "Dots");
586
1559
  }
1560
+ arrowParams(get, out);
1561
+ lineLabelParams(get, out, approximate);
587
1562
  const target = get("targetArrow");
588
1563
  if (target !== null && target !== (directed ? "triangle" : "none")) {
589
1564
  approximate("targetArrow", target);
@@ -594,47 +1569,60 @@ function lineParams(get, directed, approximate) {
594
1569
  }
595
1570
  return out;
596
1571
  }
597
- function pajekDots(lineStyle, approximate) {
598
- if (lineStyle === "dotted") {
599
- return true;
1572
+ function arrowParams(get, out) {
1573
+ const arrowSize = get("arrowSize");
1574
+ if (typeof arrowSize === "number" && arrowSize !== 1) {
1575
+ out.set("s", arrowSize);
1576
+ }
1577
+ const position = get("arrowPosition");
1578
+ if (typeof position === "number" && position > 0) {
1579
+ out.set("ap", position);
600
1580
  }
601
- approximate("lineStyle", lineStyle);
602
- return lineStyle === "dashed" || lineStyle === "dash-dot" || lineStyle === "long-dash";
603
1581
  }
604
- function getter(picture, target) {
605
- const columns = /* @__PURE__ */ new Map();
606
- for (const p of PAJEK_STYLE_CAPABILITIES[target]) {
607
- columns.set(p, picture(target, p));
1582
+ function lineLabelParams(get, out, approximate) {
1583
+ const label = get("label");
1584
+ if (typeof label === "string" && label !== "") {
1585
+ const text = pajekLabelText(label);
1586
+ if (text !== label) {
1587
+ approximate("label", label);
1588
+ }
1589
+ out.set("l", text);
1590
+ }
1591
+ const labelColor = get("labelColor");
1592
+ if (typeof labelColor === "string") {
1593
+ out.set("lc", pajekColorText(labelColor));
1594
+ }
1595
+ const labelSize = get("labelSize");
1596
+ if (typeof labelSize === "number") {
1597
+ out.set("fos", labelSize);
608
1598
  }
609
- return (i) => (property) => columns.get(property)?.[i] ?? null;
1599
+ fontParam(get, out);
610
1600
  }
611
- function exactFromBlock(snapshot, text, read) {
612
- const parsed = parseStyleBlock(text, styleFingerprint(snapshot));
613
- const ex = parsed.ok ? blockStyles(parsed.block, snapshot, "pajek") : null;
614
- if (ex === null) {
615
- return;
1601
+ function pajekDots(lineStyle, params, directed, approximate) {
1602
+ if (lineStyle === pajekDash((key) => params.get(key) ?? null, directed)) {
1603
+ return true;
616
1604
  }
1605
+ approximate("lineStyle", lineStyle);
1606
+ return ["dashed", "dotted", "dash-dot", "long-dash"].includes(lineStyle);
1607
+ }
1608
+ function exactFromBlock(snapshot, text, read, labels) {
617
1609
  const notes = new StyleNotes();
618
1610
  const directed = directedEdges(snapshot);
619
- for (const target of ["node", "edge"]) {
620
- const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
621
- const get = getter((t, p) => resolveStyles(ex, t, p, snapshot), target);
622
- const values = read[target];
623
- for (let i = 0; i < n; i++) {
624
- const want = get(i);
625
- const back = writtenAndReadBack(target, want, directed[i], notes);
626
- for (const property of READ[target]) {
627
- const native = values[property]?.[i] ?? null;
628
- const w = want(property);
629
- if (w !== null && native !== w && native === (back.get(property) ?? null)) {
630
- values[property] ??= new Array(n).fill(null);
631
- values[property][i] = w;
632
- }
633
- }
634
- }
635
- }
1611
+ takeFromBlock(snapshot, text, "pajek", (target) => ({
1612
+ values: read[target],
1613
+ properties: READ[target],
1614
+ writes: PAJEK_STYLE_CAPABILITIES[target],
1615
+ readBack: (i, want) => {
1616
+ const back = writtenAndReadBack(target, want, directed[i], notes, labels);
1617
+ return (property) => back.get(property) ?? null;
1618
+ },
1619
+ // a label the block places by a side clears the offsets its `lphi` reads back as
1620
+ take: (property, wanted) => wanted !== null || LABEL_PLACE.has(property) || OUTLINE.has(property)
1621
+ }));
636
1622
  }
637
- function writtenAndReadBack(target, want, directed, notes) {
1623
+ const OUTLINE = /* @__PURE__ */ new Set(["shapePoints", "shapePointsStretch"]);
1624
+ const LABEL_PLACE = /* @__PURE__ */ new Set(["labelOffsetX", "labelOffsetY", "labelShiftX"]);
1625
+ function writtenAndReadBack(target, want, directed, notes, labels) {
638
1626
  const ignore = () => void 0;
639
1627
  const params = target === "node" ? vertexParams(want, ignore) : lineParams(want, directed, ignore);
640
1628
  const back = /* @__PURE__ */ new Map();
@@ -642,15 +1630,26 @@ function writtenAndReadBack(target, want, directed, notes) {
642
1630
  if (typeof label === "string") {
643
1631
  params.set(LABEL_COLUMN, pajekLabelText(label));
644
1632
  }
645
- (target === "node" ? readVertex : readLine)(
646
- (key) => params.get(key) ?? null,
647
- (property, value) => {
648
- if (value !== null) {
649
- back.set(property, value);
650
- }
651
- },
652
- (property) => ({ notes, target, property })
653
- );
1633
+ if (target === "node" && [...params.keys()].every((key) => key === LABEL_COLUMN)) {
1634
+ params.set(SHAPE_COLUMN, "ellipse");
1635
+ }
1636
+ for (const key of target === "edge" ? CARRIED.edge : []) {
1637
+ if (!params.has(key)) {
1638
+ params.set(key, lineRestated(key, directed));
1639
+ }
1640
+ }
1641
+ const get = (key) => params.get(key) ?? null;
1642
+ const put = (property, value) => {
1643
+ if (value !== null) {
1644
+ back.set(property, value);
1645
+ }
1646
+ };
1647
+ const at = (property) => ({ notes, target, property });
1648
+ if (target === "node") {
1649
+ readVertex(get, put, at);
1650
+ } else {
1651
+ readLine(get, put, at, directed, labels);
1652
+ }
654
1653
  return back;
655
1654
  }
656
1655
  function pajekStyledExport(snapshot, input) {
@@ -665,14 +1664,15 @@ function pajekStyledExport(snapshot, input) {
665
1664
  const approximate = (property, value) => {
666
1665
  approximated.add(target, property, value);
667
1666
  };
668
- const get = getter((t, p) => input.picture(t, p), target);
1667
+ const get = elementValues((t, p) => input.picture(t, p), target, PAJEK_STYLE_CAPABILITIES[target]);
669
1668
  const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
670
1669
  const params = (i) => target === "node" ? vertexParams(get(i), approximate) : lineParams(get(i), directed[i], approximate);
671
- replaceParamColumns(
672
- table,
673
- target === "node" ? [SHAPE_COLUMN, ...NODE_KEYS] : EDGE_KEYS,
674
- paramColumns(n, params)
675
- );
1670
+ const columns = paramColumns(n, params);
1671
+ if (target === "edge") {
1672
+ keepLineLabels(snapshot, columns);
1673
+ }
1674
+ restateCarried(target, columns, directed);
1675
+ replaceParamColumns(table, target === "node" ? [SHAPE_COLUMN, ...NODE_KEYS] : EDGE_KEYS, columns);
676
1676
  }
677
1677
  out.nodes.set(
678
1678
  LABEL_COLUMN,
@@ -687,6 +1687,23 @@ function pajekStyledExport(snapshot, input) {
687
1687
  notes.push(...styleBlockLosses(block, input.rules.styles.rules.length, "size"));
688
1688
  return { snapshot: out, comment: PAJEK_STYLE_COMMENT + block, notes };
689
1689
  }
1690
+ function keepLineLabels(snapshot, columns) {
1691
+ if (!snapshot.edges.has("l")) {
1692
+ return;
1693
+ }
1694
+ const own = (e) => plainCell(snapshot.edges.value("l", e));
1695
+ let col = columns.get("l");
1696
+ for (let e = 0; e < snapshot.edgeCount; e++) {
1697
+ const v = own(e);
1698
+ if (typeof v === "string" && v !== "" && (col?.[e] ?? null) === null) {
1699
+ col ??= new Array(snapshot.edgeCount).fill(null);
1700
+ col[e] = pajekLabelText(v);
1701
+ }
1702
+ }
1703
+ if (col !== void 0) {
1704
+ columns.set("l", col);
1705
+ }
1706
+ }
690
1707
  function drawnLabels(input, n, approximated) {
691
1708
  const drawn = input.picture("node", "label");
692
1709
  const out = new Array(n).fill("");
@@ -715,6 +1732,47 @@ function replaceParamColumns(table, keys, columns) {
715
1732
  table.set(key, col, { dtype: numeric ? "f64" : "string" });
716
1733
  }
717
1734
  }
1735
+ function restateCarried(target, columns, directed) {
1736
+ if (target === "node") {
1737
+ const all = [...columns.values()];
1738
+ if (all.length === 0) {
1739
+ return;
1740
+ }
1741
+ const n = all[0].length;
1742
+ const shape = columns.get(SHAPE_COLUMN) ?? new Array(n).fill(null);
1743
+ for (let i = 0; i < n; i++) {
1744
+ if (all.every((col) => col[i] === null)) {
1745
+ shape[i] = "ellipse";
1746
+ }
1747
+ }
1748
+ columns.set(SHAPE_COLUMN, shape);
1749
+ return;
1750
+ }
1751
+ for (const key of CARRIED.edge) {
1752
+ const col = columns.get(key);
1753
+ if (col === void 0) {
1754
+ continue;
1755
+ }
1756
+ for (let i = 0; i < col.length; i++) {
1757
+ col[i] ??= lineRestated(key, directed[i]);
1758
+ }
1759
+ }
1760
+ }
1761
+ function lineRestated(key, directed) {
1762
+ const defaults = lineDefaults(directed);
1763
+ switch (key) {
1764
+ case "c":
1765
+ return pajekColorText(String(defaults.color));
1766
+ case "w":
1767
+ return directed ? Number(defaults.width) : Number(defaults.width) / EDGE_WIDTH_PER_W;
1768
+ case "p":
1769
+ return "Solid";
1770
+ case "s":
1771
+ return 1;
1772
+ default:
1773
+ return 0;
1774
+ }
1775
+ }
718
1776
  function paramColumns(n, params) {
719
1777
  const columns = /* @__PURE__ */ new Map();
720
1778
  for (let i = 0; i < n; i++) {
@@ -815,58 +1873,58 @@ const CAPABILITIES = capabilities({
815
1873
  });
816
1874
  function plan(table, domain, notes) {
817
1875
  const planned = [];
818
- for (const column of table) {
819
- const slot = columnSlot(column, domain, notes);
1876
+ for (const column2 of table) {
1877
+ const slot = columnSlot(column2, domain, notes);
820
1878
  if (slot !== null) {
821
- planned.push({ column, slot });
1879
+ planned.push({ column: column2, slot });
822
1880
  }
823
1881
  }
824
1882
  return planned;
825
1883
  }
826
- function columnNote(notes, code, message, column) {
827
- notes?.push(note(code, message, column.meta.name, column.length - column.nullCount));
1884
+ function columnNote(notes, code, message, column2) {
1885
+ notes?.push(note(code, message, column2.meta.name, column2.length - column2.nullCount));
828
1886
  }
829
- function columnSlot(column, domain, notes) {
830
- const { role, name } = column.meta;
1887
+ function columnSlot(column2, domain, notes) {
1888
+ const { role, name } = column2.meta;
831
1889
  if (role === "label" && domain === "node") {
832
- return labelSlot(column, notes);
1890
+ return labelSlot(column2, notes);
833
1891
  }
834
1892
  if (role === "position") {
835
- return positionSlot(column, domain, notes);
1893
+ return positionSlot(column2, domain, notes);
836
1894
  }
837
1895
  if (role === "spells") {
838
- return spellsSlot(column, domain, notes);
1896
+ return spellsSlot(column2, domain, notes);
839
1897
  }
840
1898
  if (role !== null && DROPPED_TEMPORAL_ROLES.has(role)) {
841
1899
  columnNote(
842
1900
  notes,
843
1901
  PAJEK_LOSS.TEMPORAL_DROPPED,
844
1902
  `${domain} column "${name}" (${role}) cannot be written; Pajek intervals come from the spells role`,
845
- column
1903
+ column2
846
1904
  );
847
1905
  return null;
848
1906
  }
849
- if (writtenElsewhere(column, domain)) {
1907
+ if (writtenElsewhere(column2, domain)) {
850
1908
  return null;
851
1909
  }
852
- return namedSlot(column, domain, notes);
1910
+ return namedSlot(column2, domain, notes);
853
1911
  }
854
- function labelSlot(column, notes) {
855
- const { name, dtype } = column.meta;
1912
+ function labelSlot(column2, notes) {
1913
+ const { name, dtype } = column2.meta;
856
1914
  if (dtype !== "string" && dtype !== "dict") {
857
1915
  columnNote(
858
1916
  notes,
859
1917
  PAJEK_LOSS.LABEL_AS_TEXT,
860
1918
  `node column "${name}" (label) is ${dtype}; labels are text and re-import as string`,
861
- column
1919
+ column2
862
1920
  );
863
1921
  }
864
1922
  return "label";
865
1923
  }
866
- function positionSlot(column, domain, notes) {
867
- const { name, components } = column.meta;
1924
+ function positionSlot(column2, domain, notes) {
1925
+ const { name, components } = column2.meta;
868
1926
  if (domain === "edge") {
869
- columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column);
1927
+ columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column2);
870
1928
  return null;
871
1929
  }
872
1930
  if (components === 2 || components === 3) {
@@ -876,12 +1934,12 @@ function positionSlot(column, domain, notes) {
876
1934
  notes,
877
1935
  PAJEK_LOSS.POSITION_STRIDE,
878
1936
  `node column "${name}" (position) has ${components} components; Pajek coordinates are x y [z]`,
879
- column
1937
+ column2
880
1938
  );
881
1939
  return null;
882
1940
  }
883
- function spellsSlot(column, domain, notes) {
884
- const { name, dtype, itemDtype } = column.meta;
1941
+ function spellsSlot(column2, domain, notes) {
1942
+ const { name, dtype, itemDtype } = column2.meta;
885
1943
  if (dtype === "list" && (itemDtype === "f64" || itemDtype === "i32" || itemDtype === "f32")) {
886
1944
  return "spells";
887
1945
  }
@@ -889,22 +1947,22 @@ function spellsSlot(column, domain, notes) {
889
1947
  notes,
890
1948
  LOSS.SPELLS,
891
1949
  `${domain} column "${name}" (spells) is not a list of number pairs; it cannot be written`,
892
- column
1950
+ column2
893
1951
  );
894
1952
  return null;
895
1953
  }
896
- function writtenElsewhere(column, domain) {
897
- const { role, dtype } = column.meta;
1954
+ function writtenElsewhere(column2, domain) {
1955
+ const { role, dtype } = column2.meta;
898
1956
  if (role !== null && (STRUCTURAL_ROLES.has(role) || CHECKED_ROLES.has(role))) {
899
1957
  return true;
900
1958
  }
901
1959
  return domain === "edge" && role === "id" || dtype === "list" || dtype === "json";
902
1960
  }
903
- function namedSlot(column, domain, notes) {
904
- const { name, dtype } = column.meta;
1961
+ function namedSlot(column2, domain, notes) {
1962
+ const { name, dtype } = column2.meta;
905
1963
  const text = dtype === "dict" || dtype === "string";
906
1964
  if (text && domain === "node" && name === SHAPE_COLUMN) {
907
- return shapeSlot(column, notes);
1965
+ return shapeSlot(column2, notes);
908
1966
  }
909
1967
  if (text && domain === "edge" && name === RELATION_COLUMN) {
910
1968
  return "relation";
@@ -914,22 +1972,22 @@ function namedSlot(column, domain, notes) {
914
1972
  notes,
915
1973
  PAJEK_LOSS.KEY_DROPPED,
916
1974
  `${domain} column "${name}" cannot be a Pajek parameter key; it is not written`,
917
- column
1975
+ column2
918
1976
  );
919
1977
  return null;
920
1978
  }
921
1979
  return "param";
922
1980
  }
923
- function shapeSlot(column, notes) {
924
- if (allShapeKeywords(column)) {
1981
+ function shapeSlot(column2, notes) {
1982
+ if (allShapeKeywords(column2)) {
925
1983
  return "shape";
926
1984
  }
927
- if (column.meta.dtype === "dict") {
1985
+ if (column2.meta.dtype === "dict") {
928
1986
  columnNote(
929
1987
  notes,
930
1988
  PAJEK_LOSS.SHAPE_AS_PARAMETER,
931
- `node column "${column.meta.name}" holds values outside the Pajek shape keywords; it is written as a parameter and reads back as string`,
932
- column
1989
+ `node column "${column2.meta.name}" holds values outside the Pajek shape keywords; it is written as a parameter and reads back as string`,
1990
+ column2
933
1991
  );
934
1992
  }
935
1993
  return "param";
@@ -937,9 +1995,9 @@ function shapeSlot(column, notes) {
937
1995
  function labelNotes(snapshot, nodePlan, notes) {
938
1996
  let labels = null;
939
1997
  let carried = 0;
940
- for (const { column, slot } of nodePlan) {
1998
+ for (const { column: column2, slot } of nodePlan) {
941
1999
  if (slot === "label") {
942
- labels = column;
2000
+ labels = column2;
943
2001
  } else if (slot !== "skip" && slot !== "relation") {
944
2002
  carried++;
945
2003
  }
@@ -986,16 +2044,16 @@ function unlabeled(nodeCount, labels) {
986
2044
  }
987
2045
  return count;
988
2046
  }
989
- function allShapeKeywords(column) {
990
- for (let r = 0; r < column.length; r++) {
991
- if (column.isSet(r) && !SHAPES$1.has(column.value(r))) {
2047
+ function allShapeKeywords(column2) {
2048
+ for (let r = 0; r < column2.length; r++) {
2049
+ if (column2.isSet(r) && !SHAPES$1.has(column2.value(r))) {
992
2050
  return false;
993
2051
  }
994
2052
  }
995
2053
  return true;
996
2054
  }
997
- function note(code, message, column = null, count = null) {
998
- return Object.freeze({ code, message, column, count });
2055
+ function note(code, message, column2 = null, count = null) {
2056
+ return Object.freeze({ code, message, column: column2, count });
999
2057
  }
1000
2058
  function numberText(value, dtype) {
1001
2059
  switch (dtype) {
@@ -1013,53 +2071,53 @@ function numberText(value, dtype) {
1013
2071
  }
1014
2072
  }
1015
2073
  }
1016
- function cellText(column, row) {
1017
- switch (column.dtype) {
2074
+ function cellText(column2, row) {
2075
+ switch (column2.dtype) {
1018
2076
  case "f32":
1019
2077
  case "f64":
1020
2078
  case "i32":
1021
2079
  case "u32":
1022
2080
  case "u8": {
1023
- const value = column.value(row);
2081
+ const value = column2.value(row);
1024
2082
  if (typeof value === "number") {
1025
- return numberText(value, column.dtype);
2083
+ return numberText(value, column2.dtype);
1026
2084
  }
1027
2085
  const parts = [];
1028
2086
  const vector = value;
1029
2087
  for (let k = 0; k < vector.length; k++) {
1030
- parts.push(numberText(vector[k], column.dtype));
2088
+ parts.push(numberText(vector[k], column2.dtype));
1031
2089
  }
1032
2090
  return parts.join(" ");
1033
2091
  }
1034
2092
  case "bool":
1035
- return column.value(row) === true ? "true" : "false";
2093
+ return column2.value(row) === true ? "true" : "false";
1036
2094
  case "dict":
1037
2095
  case "string":
1038
- return column.value(row);
2096
+ return column2.value(row);
1039
2097
  case "list":
1040
2098
  case "json":
1041
- return JSON.stringify(column.value(row));
2099
+ return JSON.stringify(column2.value(row));
1042
2100
  default: {
1043
- const name = column.dtype;
2101
+ const name = column2.dtype;
1044
2102
  throw new Error(`unknown dtype ${name}`);
1045
2103
  }
1046
2104
  }
1047
2105
  }
1048
2106
  function checkCells(planned, domain, notes) {
1049
- for (const { column, slot } of planned) {
2107
+ for (const { column: column2, slot } of planned) {
1050
2108
  if (slot === "position" || slot === "spells") {
1051
2109
  continue;
1052
2110
  }
1053
- const { name } = column.meta;
2111
+ const { name } = column2.meta;
1054
2112
  let badText = 0;
1055
2113
  let nonFinite = 0;
1056
2114
  let typed = 0;
1057
- for (let r = 0; r < column.length; r++) {
1058
- if (!column.isSet(r)) {
2115
+ for (let r = 0; r < column2.length; r++) {
2116
+ if (!column2.isSet(r)) {
1059
2117
  continue;
1060
2118
  }
1061
- if (column.dtype === "f64" || column.dtype === "f32") {
1062
- const value = column.value(r);
2119
+ if (column2.dtype === "f64" || column2.dtype === "f32") {
2120
+ const value = column2.value(r);
1063
2121
  if (typeof value === "number") {
1064
2122
  if (!Number.isFinite(value)) {
1065
2123
  nonFinite++;
@@ -1067,8 +2125,8 @@ function checkCells(planned, domain, notes) {
1067
2125
  } else if (value !== void 0 && !Array.from(value).every((v) => Number.isFinite(v))) {
1068
2126
  nonFinite++;
1069
2127
  }
1070
- } else if (column.dtype === "string" || column.dtype === "dict") {
1071
- const text = column.value(r);
2128
+ } else if (column2.dtype === "string" || column2.dtype === "dict") {
2129
+ const text = column2.value(r);
1072
2130
  if (!isPajekLabel(text)) {
1073
2131
  badText++;
1074
2132
  } else if (slot === "param" && inferTextDtype(text) !== "string") {
@@ -1131,11 +2189,11 @@ function labelOf(labels, ids, i, needed) {
1131
2189
  }
1132
2190
  return null;
1133
2191
  }
1134
- function spellsText(column, row) {
1135
- if (column.dtype !== "list" || !column.isSet(row)) {
2192
+ function spellsText(column2, row) {
2193
+ if (column2.dtype !== "list" || !column2.isSet(row)) {
1136
2194
  return null;
1137
2195
  }
1138
- const items = column.sliceOf(row);
2196
+ const items = column2.sliceOf(row);
1139
2197
  if (items.length === 0) {
1140
2198
  return null;
1141
2199
  }
@@ -1146,29 +2204,29 @@ function spellsText(column, row) {
1146
2204
  }
1147
2205
  return formatIntervals(pairs);
1148
2206
  }
1149
- function coordinatesText(column, i, writeZ) {
1150
- if (!column.isSet(i)) {
2207
+ function coordinatesText(column2, i, writeZ) {
2208
+ if (!column2.isSet(i)) {
1151
2209
  return null;
1152
2210
  }
1153
- const dtype = column.dtype;
1154
- const vector = column.value(i);
2211
+ const dtype = column2.dtype;
2212
+ const vector = column2.value(i);
1155
2213
  const x = formatNumber(vector[0], dtype);
1156
2214
  const y = formatNumber(vector[1], dtype);
1157
- if (column.meta.components === 3 && writeZ) {
2215
+ if (column2.meta.components === 3 && writeZ) {
1158
2216
  return `${x} ${y} ${formatNumber(vector[2], dtype)}`;
1159
2217
  }
1160
2218
  return `${x} ${y}`;
1161
2219
  }
1162
- function needsZ(column) {
1163
- if (column.meta.components !== 3) {
2220
+ function needsZ(column2) {
2221
+ if (column2.meta.components !== 3) {
1164
2222
  return false;
1165
2223
  }
1166
- if (column.meta.extra.sourceDims !== 2) {
2224
+ if (column2.meta.extra.sourceDims !== 2) {
1167
2225
  return true;
1168
2226
  }
1169
- for (let i = 0; i < column.length; i++) {
1170
- if (column.isSet(i)) {
1171
- const vector = column.value(i);
2227
+ for (let i = 0; i < column2.length; i++) {
2228
+ if (column2.isSet(i)) {
2229
+ const vector = column2.value(i);
1172
2230
  if (vector[2] !== 0) {
1173
2231
  return true;
1174
2232
  }
@@ -1251,27 +2309,49 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
1251
2309
  }
1252
2310
  }
1253
2311
  function* writeVertices(snapshot, ids, nodePlan, mangle) {
1254
- let labels = null;
1255
- let position = null;
1256
- let shape = null;
1257
- let nodeSpells = null;
1258
- const nodeParams = [];
1259
- for (const { column, slot } of nodePlan) {
2312
+ const slots = vertexSlots(nodePlan);
2313
+ const writeZ = slots.position !== null && needsZ(slots.position);
2314
+ for (let i = 0; i < snapshot.nodeCount; i++) {
2315
+ const parts = vertexParts(slots, i, writeZ);
2316
+ if (mangle && ids.isChanged(i)) {
2317
+ parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
2318
+ }
2319
+ if (slots.spells !== null) {
2320
+ const spells = spellsText(slots.spells, i);
2321
+ if (spells !== null) {
2322
+ parts.push(spells);
2323
+ }
2324
+ }
2325
+ const label = labelOf(slots.labels, ids, i, parts.length > 0);
2326
+ let line = String(i + 1);
2327
+ if (label !== null) {
2328
+ line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
2329
+ }
2330
+ if (parts.length > 0) {
2331
+ line += ` ${parts.join(" ")}`;
2332
+ }
2333
+ yield `${line}
2334
+ `;
2335
+ }
2336
+ }
2337
+ function vertexSlots(nodePlan) {
2338
+ const slots = { labels: null, position: null, shape: null, spells: null, params: [] };
2339
+ for (const { column: column2, slot } of nodePlan) {
1260
2340
  switch (slot) {
1261
2341
  case "label":
1262
- labels = column;
2342
+ slots.labels = column2;
1263
2343
  break;
1264
2344
  case "position":
1265
- position = column;
2345
+ slots.position = column2;
1266
2346
  break;
1267
2347
  case "shape":
1268
- shape = column;
2348
+ slots.shape = column2;
1269
2349
  break;
1270
2350
  case "spells":
1271
- nodeSpells = column;
2351
+ slots.spells = column2;
1272
2352
  break;
1273
2353
  case "param":
1274
- nodeParams.push(column);
2354
+ slots.params.push(column2);
1275
2355
  break;
1276
2356
  case "relation":
1277
2357
  case "skip":
@@ -1282,48 +2362,32 @@ function* writeVertices(snapshot, ids, nodePlan, mangle) {
1282
2362
  }
1283
2363
  }
1284
2364
  }
1285
- const writeZ = position !== null && needsZ(position);
1286
- for (let i = 0; i < snapshot.nodeCount; i++) {
1287
- const parts = [];
1288
- if (position !== null) {
1289
- const coordinates = coordinatesText(position, i, writeZ);
1290
- if (coordinates !== null) {
1291
- parts.push(coordinates);
1292
- }
1293
- }
1294
- if (shape?.isSet(i)) {
1295
- const keyword = cellText(shape, i);
1296
- if (SHAPES$1.has(keyword)) {
1297
- parts.push(keyword);
1298
- } else {
1299
- parts.push(`${SHAPE_COLUMN} ${quotePajekLabel(keyword)}`);
1300
- }
1301
- }
1302
- for (const column of nodeParams) {
1303
- if (column.isSet(i)) {
1304
- parts.push(`${column.meta.name} ${quotePajekLabel(cellText(column, i))}`);
1305
- }
1306
- }
1307
- if (mangle && ids.isChanged(i)) {
1308
- parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
1309
- }
1310
- if (nodeSpells !== null) {
1311
- const spells = spellsText(nodeSpells, i);
1312
- if (spells !== null) {
1313
- parts.push(spells);
1314
- }
1315
- }
1316
- const label = labelOf(labels, ids, i, parts.length > 0);
1317
- let line = String(i + 1);
1318
- if (label !== null) {
1319
- line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
2365
+ return slots;
2366
+ }
2367
+ function vertexParts(slots, i, writeZ) {
2368
+ const { position, shape } = slots;
2369
+ const parts = [];
2370
+ const coordinates = position === null ? null : coordinatesText(position, i, writeZ);
2371
+ if (coordinates !== null) {
2372
+ parts.push(coordinates);
2373
+ }
2374
+ const placed = parts.length > 0;
2375
+ const shaped = shape?.isSet(i) === true;
2376
+ if (shaped) {
2377
+ const keyword = cellText(shape, i);
2378
+ parts.push(SHAPES$1.has(keyword) ? keyword : `${SHAPE_COLUMN} ${quotePajekLabel(keyword)}`);
2379
+ }
2380
+ const named = parts.length;
2381
+ for (const column2 of slots.params) {
2382
+ if (!column2.isSet(i)) {
2383
+ continue;
1320
2384
  }
1321
- if (parts.length > 0) {
1322
- line += ` ${parts.join(" ")}`;
2385
+ if (placed && !shaped && parts.length === named && VOIDING_KEYS.has(column2.meta.name)) {
2386
+ parts.push("ellipse");
1323
2387
  }
1324
- yield `${line}
1325
- `;
2388
+ parts.push(`${column2.meta.name} ${quotePajekLabel(cellText(column2, i))}`);
1326
2389
  }
2390
+ return parts;
1327
2391
  }
1328
2392
  function* writeLines(snapshot, edgePlan) {
1329
2393
  const folding = pairFolding(snapshot, { foldMutual: true });
@@ -1332,16 +2396,16 @@ function* writeLines(snapshot, edgePlan) {
1332
2396
  let relation = null;
1333
2397
  let edgeSpells = null;
1334
2398
  const edgeParams = [];
1335
- for (const { column, slot } of edgePlan) {
2399
+ for (const { column: column2, slot } of edgePlan) {
1336
2400
  switch (slot) {
1337
2401
  case "relation":
1338
- relation = column;
2402
+ relation = column2;
1339
2403
  break;
1340
2404
  case "spells":
1341
- edgeSpells = column;
2405
+ edgeSpells = column2;
1342
2406
  break;
1343
2407
  case "param":
1344
- edgeParams.push(column);
2408
+ edgeParams.push(column2);
1345
2409
  break;
1346
2410
  case "label":
1347
2411
  case "position":
@@ -1388,9 +2452,9 @@ function* writeLines(snapshot, edgePlan) {
1388
2452
  if (weight !== null) {
1389
2453
  line += ` ${weight}`;
1390
2454
  }
1391
- for (const column of edgeParams) {
1392
- if (column.isSet(e)) {
1393
- line += ` ${column.meta.name} ${quotePajekLabel(cellText(column, e))}`;
2455
+ for (const column2 of edgeParams) {
2456
+ if (column2.isSet(e)) {
2457
+ line += ` ${column2.meta.name} ${quotePajekLabel(cellText(column2, e))}`;
1394
2458
  }
1395
2459
  }
1396
2460
  if (edgeSpells !== null) {
@@ -1478,16 +2542,16 @@ function withOriginalIds(options) {
1478
2542
  }
1479
2543
  function ownedColumns(snapshot, planned) {
1480
2544
  const owned = /* @__PURE__ */ new Set();
1481
- const key = (column) => `${column.meta.domain}:${column.meta.name}`;
1482
- for (const { column, slot } of planned) {
1483
- const shapeParam = slot === "param" && column.meta.domain === "node" && column.meta.name === SHAPE_COLUMN;
2545
+ const key = (column2) => `${column2.meta.domain}:${column2.meta.name}`;
2546
+ for (const { column: column2, slot } of planned) {
2547
+ const shapeParam = slot === "param" && column2.meta.domain === "node" && column2.meta.name === SHAPE_COLUMN;
1484
2548
  if (slot === "shape" || slot === "relation" || shapeParam) {
1485
- owned.add(key(column));
2549
+ owned.add(key(column2));
1486
2550
  }
1487
2551
  }
1488
- for (const column of [...snapshot.nodes, ...snapshot.edges]) {
1489
- if (column.meta.role === "spells") {
1490
- owned.add(key(column));
2552
+ for (const column2 of [...snapshot.nodes, ...snapshot.edges]) {
2553
+ if (column2.meta.role === "spells") {
2554
+ owned.add(key(column2));
1491
2555
  }
1492
2556
  }
1493
2557
  return owned;
@@ -1530,13 +2594,13 @@ function checkPlain(snapshot, options) {
1530
2594
  const owned = ownedColumns(snapshot, [...nodePlan, ...edgePlan]);
1531
2595
  notes.push(...capabilityNotes(snapshot, resolved, owned));
1532
2596
  labelNotes(snapshot, nodePlan, notes);
1533
- for (const column of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
2597
+ for (const column2 of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
1534
2598
  notes.push(
1535
2599
  note(
1536
2600
  LOSS.ROLE,
1537
- `edge column "${column.meta.name}" (label) is written as a plain parameter; Pajek labels vertices only and the role is lost`,
1538
- column.meta.name,
1539
- column.length - column.nullCount
2601
+ `edge column "${column2.meta.name}" (label) is written as a plain parameter; Pajek labels vertices only and the role is lost`,
2602
+ column2.meta.name,
2603
+ column2.length - column2.nullCount
1540
2604
  )
1541
2605
  );
1542
2606
  }
@@ -1731,7 +2795,7 @@ function spellsDecl() {
1731
2795
  origin: { format: "pajek", id: "interval" }
1732
2796
  };
1733
2797
  }
1734
- function positionDecl(sourceDims) {
2798
+ function positionDecl(sourceDims, window) {
1735
2799
  return {
1736
2800
  name: POSITION_COLUMN,
1737
2801
  dtype: "f64",
@@ -1740,10 +2804,21 @@ function positionDecl(sourceDims) {
1740
2804
  role: "position",
1741
2805
  origin: { format: "pajek", id: "coordinates" },
1742
2806
  // Pajek draws y downward (USAir97.net has Deadhorse, Alaska at y 0.10 and Miami at 0.53),
1743
- // centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position
1744
- extra: { sourceDims, units: "file", yAxis: "down", zOrigin: 0.5, zeroUnplaced: true }
2807
+ // centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position; one unit
2808
+ // is the Draw window's width in points across and its height down (500 each by default,
2809
+ // PAJEK_POINTS_PER_UNIT): Pajek stretches 0..1 to the window one axis at a time
2810
+ extra: {
2811
+ sourceDims,
2812
+ units: "file",
2813
+ pxPerUnit: window.width,
2814
+ ...window.height === window.width ? {} : { pxPerUnitY: window.height },
2815
+ yAxis: "down",
2816
+ zOrigin: 0.5,
2817
+ zeroUnplaced: true
2818
+ }
1745
2819
  };
1746
2820
  }
2821
+ const DEFAULT_WINDOW = { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
1747
2822
  class LineError extends Error {
1748
2823
  /**
1749
2824
  * Create a line error.
@@ -1770,8 +2845,11 @@ class PajekParser {
1770
2845
  * @param report - the report
1771
2846
  * @param options - the resolved common options
1772
2847
  * @param firstVertex - the firstVertex format option
2848
+ * @param window - the Draw window the coordinates are stretched to
1773
2849
  */
1774
- constructor(sink, report, options, firstVertex) {
2850
+ constructor(sink, report, options, firstVertex, window = DEFAULT_WINDOW) {
2851
+ this.keptBlock = null;
2852
+ this.voided = [];
1775
2853
  this.section = "none";
1776
2854
  this.kind = "directed";
1777
2855
  this.relation = null;
@@ -1808,6 +2886,7 @@ class PajekParser {
1808
2886
  this.ended = false;
1809
2887
  this.edgeParams = /* @__PURE__ */ new Map();
1810
2888
  this.styleBlockKept = false;
2889
+ this.window = window;
1811
2890
  this.sink = sink;
1812
2891
  this.report = report;
1813
2892
  this.options = options;
@@ -1827,7 +2906,8 @@ class PajekParser {
1827
2906
  const trimmed = text.trimStart();
1828
2907
  if (trimmed.startsWith(PAJEK_STYLE_COMMENT)) {
1829
2908
  this.styleBlockKept = true;
1830
- this.report.keepForStyles(trimmed.slice(PAJEK_STYLE_COMMENT.length));
2909
+ this.keptBlock = trimmed.slice(PAJEK_STYLE_COMMENT.length);
2910
+ this.report.keepForStyles(this.keptBlock);
1831
2911
  }
1832
2912
  }
1833
2913
  /**
@@ -2290,6 +3370,55 @@ class PajekParser {
2290
3370
  */
2291
3371
  vertexLine(text, line) {
2292
3372
  const tokens = this.tokens(text, "node", line);
3373
+ const { k, pos } = this.vertexNumber(tokens, line);
3374
+ let i = 1;
3375
+ let label = null;
3376
+ if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
3377
+ label = this.labelOf(tokens[1], k, line);
3378
+ i = 2;
3379
+ }
3380
+ const { xyz, dims, next } = this.vertexCoordinates(tokens, i, k);
3381
+ i = next;
3382
+ this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
3383
+ let shape = null;
3384
+ if (i < tokens.length && isShapeKeyword(tokens[i])) {
3385
+ shape = tokens[i].toLowerCase();
3386
+ i++;
3387
+ }
3388
+ const extras = this.extras(tokens, i, "node", line);
3389
+ shape = extras.shape ?? shape;
3390
+ const restored = this.restoredId(extras);
3391
+ this.createNodes();
3392
+ const repeated = this.markVertexSeen(pos, k, line);
3393
+ const index = this.vertexIndex(pos, k, label, restored, repeated, line);
3394
+ if (shape === null && dims > 0 && extras.keys.length > 0 && VOIDING_KEYS.has(extras.keys[0])) {
3395
+ this.voided.push(index);
3396
+ }
3397
+ if (label !== null) {
3398
+ this.labelHandle = this.nodeHandle(this.labelHandle, LABEL_DECL, line);
3399
+ this.sink.setNodeValue(this.labelHandle, index, label);
3400
+ }
3401
+ if (dims > 0) {
3402
+ this.writePosition(index, dims, xyz, k, line);
3403
+ }
3404
+ if (shape !== null) {
3405
+ this.writeShape(index, shape, line);
3406
+ }
3407
+ for (let p = 0; p < extras.keys.length; p++) {
3408
+ this.writeParameter("node", extras.keys[p], index, extras.values[p]);
3409
+ }
3410
+ if (extras.spells !== null) {
3411
+ this.nodeSpellsHandle = this.nodeHandle(this.nodeSpellsHandle, spellsDecl(), line);
3412
+ this.sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
3413
+ }
3414
+ }
3415
+ /**
3416
+ * A vertex line's number, checked: it starts the line and is in the declared range.
3417
+ * @param tokens - the line's tokens
3418
+ * @param line - the line number
3419
+ * @returns the vertex number and its position
3420
+ */
3421
+ vertexNumber(tokens, line) {
2293
3422
  if (!isVertexNumber(tokens[0])) {
2294
3423
  this.report.counts.skippedNodes++;
2295
3424
  throw new LineError(
@@ -2312,27 +3441,25 @@ class PajekParser {
2312
3441
  `vertex ${k} is outside ${this.base}..${this.base + this.vertexCount - 1}`
2313
3442
  );
2314
3443
  }
2315
- let i = 1;
2316
- let label = null;
2317
- if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
2318
- label = this.labelOf(tokens[1], k, line);
2319
- i = 2;
2320
- }
2321
- let x = 0;
2322
- let y = 0;
2323
- let z = 0;
2324
- let dims = 0;
3444
+ return { k, pos };
3445
+ }
3446
+ /**
3447
+ * A vertex line's coordinates: two or three numbers, or none; a single one is an error.
3448
+ * @param tokens - the line's tokens
3449
+ * @param i - where the coordinates would start
3450
+ * @param k - the vertex number
3451
+ * @returns x, y and z (0 when absent), how many were read, and the index after them
3452
+ */
3453
+ vertexCoordinates(tokens, i, k) {
2325
3454
  if (i + 1 < tokens.length && isNumericText(tokens[i]) && isNumericText(tokens[i + 1])) {
2326
- x = Number(tokens[i]);
2327
- y = Number(tokens[i + 1]);
2328
- i += 2;
2329
- dims = 2;
2330
- if (i < tokens.length && isNumericText(tokens[i])) {
2331
- z = Number(tokens[i]);
2332
- i++;
2333
- dims = 3;
3455
+ const x = Number(tokens[i]);
3456
+ const y = Number(tokens[i + 1]);
3457
+ if (i + 2 < tokens.length && isNumericText(tokens[i + 2])) {
3458
+ return { xyz: [x, y, Number(tokens[i + 2])], dims: 3, next: i + 3 };
2334
3459
  }
2335
- } else if (i < tokens.length && isNumericText(tokens[i])) {
3460
+ return { xyz: [x, y, 0], dims: 2, next: i + 2 };
3461
+ }
3462
+ if (i < tokens.length && isNumericText(tokens[i])) {
2336
3463
  this.report.counts.skippedNodes++;
2337
3464
  throw new LineError(
2338
3465
  "parse-error",
@@ -2340,81 +3467,88 @@ class PajekParser {
2340
3467
  `vertex ${k}: a single coordinate "${tokens[i]}"; coordinates are x y [z]`
2341
3468
  );
2342
3469
  }
2343
- this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
2344
- let shape = null;
2345
- if (i < tokens.length && isShapeKeyword(tokens[i])) {
2346
- shape = tokens[i].toLowerCase();
2347
- i++;
2348
- }
2349
- const extras = this.extras(tokens, i, "node", line);
2350
- shape = extras.shape ?? shape;
2351
- const restored = this.restoredId(extras);
2352
- this.createNodes();
2353
- const repeated = this.seen[pos] !== 0;
2354
- if (repeated) {
3470
+ return { xyz: [0, 0, 0], dims: 0, next: i };
3471
+ }
3472
+ /**
3473
+ * Marks a vertex's position as having a line, warning when it already had one.
3474
+ * @param pos - the vertex's position
3475
+ * @param k - the vertex number
3476
+ * @param line - the line number
3477
+ * @returns whether the vertex already had a line
3478
+ */
3479
+ markVertexSeen(pos, k, line) {
3480
+ if (this.seen[pos] !== 0) {
2355
3481
  this.report.warning(
2356
3482
  "merged",
2357
3483
  PAJEK_ISSUE.DUPLICATE_NODE,
2358
3484
  `vertex ${k} has more than one line; the later values overwrite`,
2359
3485
  { line, element: String(k) }
2360
3486
  );
2361
- } else {
2362
- this.seen[pos] = 1;
2363
- this.seenCount++;
3487
+ return true;
2364
3488
  }
2365
- let index;
2366
- if (this.idOfPos !== null && !repeated && this.options.nodeIdFrom === "label") {
2367
- index = this.deferredNode(this.idOfPos, pos, k, label, line, "label");
2368
- } else if (this.idOfPos !== null && this.idOfPos[pos] === void 0) {
3489
+ this.seen[pos] = 1;
3490
+ this.seenCount++;
3491
+ return false;
3492
+ }
3493
+ /**
3494
+ * The node index a vertex line writes to, creating the node when its id is deferred to its line.
3495
+ * @param pos - the vertex's position
3496
+ * @param k - the vertex number
3497
+ * @param label - the line's label, or null
3498
+ * @param restored - the original id the line carries, or null
3499
+ * @param repeated - whether the vertex already had a line
3500
+ * @param line - the line number
3501
+ * @returns the node index
3502
+ */
3503
+ vertexIndex(pos, k, label, restored, repeated, line) {
3504
+ const { idOfPos } = this;
3505
+ if (idOfPos !== null && !repeated && this.options.nodeIdFrom === "label") {
3506
+ return this.deferredNode(idOfPos, pos, k, label, line, "label");
3507
+ }
3508
+ if (idOfPos !== null && idOfPos[pos] === void 0) {
2369
3509
  for (let p = this.filledBelow; p < pos; p++) {
2370
- if (this.idOfPos[p] === void 0) {
2371
- this.numberedNode(this.idOfPos, p);
3510
+ if (idOfPos[p] === void 0) {
3511
+ this.numberedNode(idOfPos, p);
2372
3512
  }
2373
3513
  }
2374
3514
  if (pos > this.filledBelow) {
2375
3515
  this.filledBelow = pos;
2376
3516
  }
2377
- index = this.deferredNode(this.idOfPos, pos, k, restored, line, "originalId");
2378
- } else {
2379
- index = this.indexOfPos[pos];
2380
- if (restored !== null && !repeated) {
2381
- this.report.warning(
2382
- "coercion",
2383
- PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
2384
- `vertex ${k} carries ${ORIGINAL_ID_KEY} ${JSON.stringify(restored)} but a later vertex's line came first and created it under its number; the original id is not restored`,
2385
- { line, element: String(k) }
2386
- );
2387
- }
2388
- }
2389
- const { sink } = this;
2390
- if (label !== null) {
2391
- if (this.labelHandle === INVALID_INDEX) {
2392
- this.labelHandle = declareResolved(sink, "node", LABEL_DECL, this.report, { line }).handle;
2393
- }
2394
- sink.setNodeValue(this.labelHandle, index, label);
2395
- }
2396
- if (dims > 0) {
2397
- this.writePosition(index, dims, [x, y, z], k, line);
3517
+ return this.deferredNode(idOfPos, pos, k, restored, line, "originalId");
2398
3518
  }
2399
- if (shape !== null) {
2400
- if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
2401
- this.writeParameter("node", SHAPE_COLUMN, index, shape);
2402
- } else {
2403
- if (this.shapeHandle === INVALID_INDEX) {
2404
- this.shapeHandle = declareResolved(sink, "node", SHAPE_DECL, this.report, { line }).handle;
2405
- }
2406
- sink.setNodeValue(this.shapeHandle, index, shape);
2407
- }
2408
- }
2409
- for (let p = 0; p < extras.keys.length; p++) {
2410
- this.writeParameter("node", extras.keys[p], index, extras.values[p]);
3519
+ if (restored !== null && !repeated) {
3520
+ this.report.warning(
3521
+ "coercion",
3522
+ PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
3523
+ `vertex ${k} carries ${ORIGINAL_ID_KEY} ${JSON.stringify(restored)} but a later vertex's line came first and created it under its number; the original id is not restored`,
3524
+ { line, element: String(k) }
3525
+ );
2411
3526
  }
2412
- if (extras.spells !== null) {
2413
- if (this.nodeSpellsHandle === INVALID_INDEX) {
2414
- this.nodeSpellsHandle = declareResolved(sink, "node", spellsDecl(), this.report, { line }).handle;
2415
- }
2416
- sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
3527
+ return this.indexOfPos[pos];
3528
+ }
3529
+ /**
3530
+ * A node column's handle, declared on first use.
3531
+ * @param handle - the handle so far, or INVALID_INDEX
3532
+ * @param decl - the column's declaration
3533
+ * @param line - the line number
3534
+ * @returns the handle
3535
+ */
3536
+ nodeHandle(handle, decl, line) {
3537
+ return handle === INVALID_INDEX ? declareResolved(this.sink, "node", decl, this.report, { line }).handle : handle;
3538
+ }
3539
+ /**
3540
+ * Writes a vertex's shape keyword: to the shape column, or to an earlier `shape "<text>"` parameter's column.
3541
+ * @param index - the node index
3542
+ * @param shape - the keyword
3543
+ * @param line - the line number
3544
+ */
3545
+ writeShape(index, shape, line) {
3546
+ if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
3547
+ this.writeParameter("node", SHAPE_COLUMN, index, shape);
3548
+ return;
2417
3549
  }
3550
+ this.shapeHandle = this.nodeHandle(this.shapeHandle, SHAPE_DECL, line);
3551
+ this.sink.setNodeValue(this.shapeHandle, index, shape);
2418
3552
  }
2419
3553
  /**
2420
3554
  * A vertex label as written, its character references decoded.
@@ -2475,7 +3609,9 @@ class PajekParser {
2475
3609
  writePosition(index, dims, point, k, line) {
2476
3610
  if (this.positionHandle === INVALID_INDEX) {
2477
3611
  this.coordDims = dims;
2478
- this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims), this.report, { line }).handle;
3612
+ this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims, this.window), this.report, {
3613
+ line
3614
+ }).handle;
2479
3615
  } else if (dims !== this.coordDims) {
2480
3616
  this.report.warnOnce(
2481
3617
  "validation-error",
@@ -2862,7 +3998,7 @@ class PajekParser {
2862
3998
  for (let i = start; i < tokens.length; ) {
2863
3999
  const token = tokens[i];
2864
4000
  if (token.startsWith("[")) {
2865
- extras.spells = this.intervals(token, domain);
4001
+ extras.spells = this.intervals(token, domain, line);
2866
4002
  i++;
2867
4003
  continue;
2868
4004
  }
@@ -2885,8 +4021,9 @@ class PajekParser {
2885
4021
  }
2886
4022
  seen.add(token);
2887
4023
  extras.keys.push(token);
2888
- extras.values.push(tokens[i + 1]);
2889
- i += 2;
4024
+ const triple = COLOR_KEYS.has(token) ? colorTriple(tokens, i + 1) : null;
4025
+ extras.values.push(triple ?? tokens[i + 1]);
4026
+ i += triple === null ? 2 : 4;
2890
4027
  }
2891
4028
  return extras;
2892
4029
  }
@@ -2915,12 +4052,15 @@ class PajekParser {
2915
4052
  );
2916
4053
  }
2917
4054
  /**
2918
- * The spells of a row's interval token; a malformed one skips the row.
4055
+ * The spells of a row's interval token. A token not closed by "]" skips the row; a closed one
4056
+ * whose times cannot be read (`[287-?]`, lin-rel4.net) is reported and dropped, and the rest of
4057
+ * the row (its label, coordinates and parameters) is kept.
2919
4058
  * @param token - the token, starting with "["
2920
- * @param domain - what is skipped when the token is malformed
2921
- * @returns the spells, or null for an empty `[]`, which is no spell at all
4059
+ * @param domain - what is skipped when the token is not closed
4060
+ * @param line - the line number
4061
+ * @returns the spells, or null for an empty `[]`, which is no spell at all, and for a dropped one
2922
4062
  */
2923
- intervals(token, domain) {
4063
+ intervals(token, domain, line) {
2924
4064
  if (!isIntervalToken(token)) {
2925
4065
  this.skip(domain);
2926
4066
  throw new LineError(
@@ -2933,12 +4073,13 @@ class PajekParser {
2933
4073
  const spells = parseIntervals(token);
2934
4074
  return spells.length === 0 ? null : spells;
2935
4075
  } catch (err) {
2936
- this.skip(domain);
2937
- throw new LineError(
4076
+ this.report.error(
2938
4077
  "validation-error",
2939
4078
  PAJEK_ISSUE.INTERVAL,
2940
- err instanceof Error ? err.message : String(err)
4079
+ `${err instanceof Error ? err.message : String(err)}; the interval is dropped and the rest of the line kept`,
4080
+ { line }
2941
4081
  );
4082
+ return null;
2942
4083
  }
2943
4084
  }
2944
4085
  /**
@@ -2976,6 +4117,12 @@ class PajekParser {
2976
4117
  writer.write(row, text);
2977
4118
  }
2978
4119
  }
4120
+ const COLOR_KEYS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
4121
+ function colorTriple(tokens, at) {
4122
+ const parts = tokens.slice(at, at + 3);
4123
+ const fraction = (t) => /^[01]?(?:\.\d+)?$/.test(t) && t !== "" && Number(t) <= 1;
4124
+ return parts.length === 3 && parts.every(fraction) ? parts.join(" ") : null;
4125
+ }
2979
4126
  function startsWithCoordinates(text, tokens) {
2980
4127
  if (quotedAfterNumber(text, tokens)) {
2981
4128
  return false;
@@ -3015,10 +4162,29 @@ function headSection(text) {
3015
4162
  }
3016
4163
  const pajekImporter = Object.freeze({
3017
4164
  format: "pajek",
3018
- options: Object.freeze(["firstVertex"]),
4165
+ options: Object.freeze(["firstVertex", "pajekDraw"]),
3019
4166
  extensions: Object.freeze([".net", ".paj"]),
3020
4167
  mimeTypes: Object.freeze(["text/x-pajek", "text/plain"]),
3021
4168
  styles: pajekStyles,
4169
+ /**
4170
+ * Where Pajek 6.02 draws a network whose vertices have no coordinates: round a circle in vertex order, the first
4171
+ * on the left, the rest going clockwise on screen (y down), at radius 0.4 about the middle of the Draw window
4172
+ * (pajek-iliad: 311 vertices 200 points from the middle of its 500-point window). A file with coordinates is read
4173
+ * from its position column.
4174
+ * @param snapshot - the imported graph
4175
+ * @returns the circle for a file with no coordinates, else null
4176
+ */
4177
+ positions(snapshot) {
4178
+ if (snapshot.nodes.byRole("position") !== null) {
4179
+ return null;
4180
+ }
4181
+ return {
4182
+ units: "file",
4183
+ pxPerUnit: PAJEK_POINTS_PER_UNIT,
4184
+ yAxis: "down",
4185
+ unplacedCircle: { center: [0.5, 0.5], radius: 0.4, startDegrees: 180, direction: 1 }
4186
+ };
4187
+ },
3022
4188
  /**
3023
4189
  * Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`),
3024
4190
  * after any `%` comment lines.
@@ -3046,10 +4212,11 @@ const pajekImporter = Object.freeze({
3046
4212
  }
3047
4213
  const resolved = resolveImportOptions(options, DEFAULTS);
3048
4214
  const firstVertex = firstVertexOption(options?.firstVertex);
4215
+ const draw = resolvePajekDraw(options?.pajekDraw);
3049
4216
  const report = new ImportReportBuilder("pajek", resolved.errorLimit);
3050
4217
  reportSinkOptions(sink, options, report);
3051
4218
  reportUnusedOptions(options, report, USED_OPTIONS);
3052
- const parser = new PajekParser(sink, report, resolved, firstVertex);
4219
+ const parser = new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
3053
4220
  const reader = new LineReader(input, report, resolved);
3054
4221
  let rest = null;
3055
4222
  let restLine = 0;
@@ -3069,6 +4236,9 @@ const pajekImporter = Object.freeze({
3069
4236
  }
3070
4237
  }
3071
4238
  parser.finish();
4239
+ if (draw !== null || parser.voided.length > 0) {
4240
+ report.keepForStyles({ block: parser.keptBlock, pajekDraw: draw ?? void 0, voided: parser.voided });
4241
+ }
3072
4242
  if (rest !== null) {
3073
4243
  const objects = rest.objects > 0 ? `; ${rest.objects} *Partition / *Vector object(s) after them are not read` : "";
3074
4244
  report.warning(
@@ -3093,13 +4263,25 @@ const pajekImporter = Object.freeze({
3093
4263
  async importAll(input, sinkFor, options) {
3094
4264
  const resolved = resolveImportOptions(options, DEFAULTS);
3095
4265
  const firstVertex = firstVertexOption(options?.firstVertex);
4266
+ const draw = resolvePajekDraw(options?.pajekDraw);
3096
4267
  const reports = [new ImportReportBuilder("pajek", resolved.errorLimit)];
3097
4268
  reportUnusedOptions(options, reports[0], USED_OPTIONS);
3098
4269
  const open = () => {
3099
4270
  const report = reports[reports.length - 1];
3100
4271
  const sink = sinkFor(reports.length - 1);
3101
4272
  reportSinkOptions(sink, options, report);
3102
- return new PajekParser(sink, report, resolved, firstVertex);
4273
+ return new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
4274
+ };
4275
+ const close = (p) => {
4276
+ p.finish();
4277
+ const last = reports.at(-1);
4278
+ if (last !== void 0 && (draw !== null || p.voided.length > 0)) {
4279
+ last.keepForStyles({
4280
+ block: p.keptBlock,
4281
+ pajekDraw: draw ?? void 0,
4282
+ voided: p.voided
4283
+ });
4284
+ }
3103
4285
  };
3104
4286
  let parser = open();
3105
4287
  const reader = new LineReader(input, reports[0], resolved);
@@ -3107,7 +4289,7 @@ const pajekImporter = Object.freeze({
3107
4289
  for await (const raw of reader) {
3108
4290
  const text = withoutStrayBom(raw);
3109
4291
  if (parser.line(text, reader.line)) {
3110
- parser.finish();
4292
+ close(parser);
3111
4293
  reports.push(new ImportReportBuilder("pajek", resolved.errorLimit));
3112
4294
  parser = open();
3113
4295
  parser.line(text, reader.line);
@@ -3117,7 +4299,7 @@ const pajekImporter = Object.freeze({
3117
4299
  throwIfAborted(resolved.signal);
3118
4300
  }
3119
4301
  }
3120
- parser.finish();
4302
+ close(parser);
3121
4303
  throwIfAborted(resolved.signal);
3122
4304
  return reports.map((r) => r.finish());
3123
4305
  }
@@ -3179,4 +4361,4 @@ export {
3179
4361
  pajekImporter as d,
3180
4362
  pajekExporter as p
3181
4363
  };
3182
- //# sourceMappingURL=importer-CVT-JyDE.js.map
4364
+ //# sourceMappingURL=importer-DgG4v1Ms.js.map