@graphty/graph-io 0.3.48 → 0.3.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (570) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-Bzn3L-je.js.map} +1 -1
  3. package/dist/chunks/bends-BGXjv_U4.js +129 -0
  4. package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
  5. package/dist/chunks/{block-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
  6. package/dist/chunks/block-iptrlMBb.js.map +1 -0
  7. package/dist/chunks/choose-CczZJaX_.js +717 -0
  8. package/dist/chunks/choose-CczZJaX_.js.map +1 -0
  9. package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
  15. package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
  16. package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
  17. package/dist/chunks/{credentials-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
  18. package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
  19. package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
  20. package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
  24. package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
  26. package/dist/chunks/emit-BwHQkZle.js.map +1 -0
  27. package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
  28. package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
  29. package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
  30. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  31. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  32. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  33. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
  34. package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
  35. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
  36. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
  39. package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
  40. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-nDfxIK5D.js.map} +1 -1
  41. package/dist/chunks/format-BXiAb-1h.js +408 -0
  42. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  43. package/dist/chunks/{generic-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
  44. package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
  45. package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
  46. package/dist/chunks/importer-B92x1xY5.js.map +1 -0
  47. package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
  48. package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
  49. package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
  50. package/dist/chunks/importer-DaLTjbds.js.map +1 -0
  51. package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
  52. package/dist/chunks/importer-GREKMdIf.js.map +1 -0
  53. package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
  54. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
  55. package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
  56. package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
  57. package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
  58. package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
  59. package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
  60. package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
  61. package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
  62. package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  63. package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
  64. package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
  65. package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
  66. package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  67. package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
  68. package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
  69. package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
  70. package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
  71. package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
  72. package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
  74. package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
  76. package/dist/chunks/styles-CCs214_3.js.map +1 -0
  77. package/dist/chunks/styles-Cm62yyQX.js +2812 -0
  78. package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
  79. package/dist/chunks/styles-DPQQIig4.js +1928 -0
  80. package/dist/chunks/styles-DPQQIig4.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
  82. package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
  83. package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
  84. package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
  85. package/dist/csv.js +7 -7
  86. package/dist/cx.js +2 -2
  87. package/dist/cx2.js +2 -2
  88. package/dist/cys.js +1 -1
  89. package/dist/dot.js +5 -4
  90. package/dist/dot.js.map +1 -1
  91. package/dist/gexf.js +42 -12
  92. package/dist/gexf.js.map +1 -1
  93. package/dist/gml.js +847 -193
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +232 -220
  96. package/dist/graph-io.js.map +1 -1
  97. package/dist/graphml.js +3 -3
  98. package/dist/json.js +3 -2
  99. package/dist/neo4j.js +6 -6
  100. package/dist/obo.js +1 -1
  101. package/dist/pajek.js +1 -1
  102. package/dist/positions.js +45 -3
  103. package/dist/positions.js.map +1 -1
  104. package/dist/sources-cypher.js +138 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +16 -6
  108. package/dist/sources-rest.js.map +1 -1
  109. package/dist/sources-sparql.d.ts +1 -0
  110. package/dist/sources-sparql.js +405 -0
  111. package/dist/sources-sparql.js.map +1 -0
  112. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  113. package/dist/src/formats/cx/importer.js +5 -1
  114. package/dist/src/formats/cx/importer.js.map +1 -1
  115. package/dist/src/formats/cx/styles.d.ts +24 -1
  116. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  117. package/dist/src/formats/cx/styles.js +117 -11
  118. package/dist/src/formats/cx/styles.js.map +1 -1
  119. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  120. package/dist/src/formats/cx2/importer.js +1 -0
  121. package/dist/src/formats/cx2/importer.js.map +1 -1
  122. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  123. package/dist/src/formats/cx2/styles.js +3 -1
  124. package/dist/src/formats/cx2/styles.js.map +1 -1
  125. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cys/importer.js +1 -0
  127. package/dist/src/formats/cys/importer.js.map +1 -1
  128. package/dist/src/formats/cys/styles.d.ts +2 -0
  129. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cys/styles.js +15 -7
  131. package/dist/src/formats/cys/styles.js.map +1 -1
  132. package/dist/src/formats/dot/drawing.d.ts +98 -0
  133. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  134. package/dist/src/formats/dot/drawing.js +734 -0
  135. package/dist/src/formats/dot/drawing.js.map +1 -0
  136. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  137. package/dist/src/formats/dot/importer.js +108 -31
  138. package/dist/src/formats/dot/importer.js.map +1 -1
  139. package/dist/src/formats/dot/label-places.d.ts +34 -0
  140. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  141. package/dist/src/formats/dot/label-places.js +179 -0
  142. package/dist/src/formats/dot/label-places.js.map +1 -0
  143. package/dist/src/formats/dot/record.d.ts +50 -0
  144. package/dist/src/formats/dot/record.d.ts.map +1 -0
  145. package/dist/src/formats/dot/record.js +275 -0
  146. package/dist/src/formats/dot/record.js.map +1 -0
  147. package/dist/src/formats/dot/styles.d.ts +62 -2
  148. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  149. package/dist/src/formats/dot/styles.js +1454 -119
  150. package/dist/src/formats/dot/styles.js.map +1 -1
  151. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  152. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  153. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  154. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  155. package/dist/src/formats/gexf/importer.d.ts +7 -0
  156. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  157. package/dist/src/formats/gexf/importer.js +41 -5
  158. package/dist/src/formats/gexf/importer.js.map +1 -1
  159. package/dist/src/formats/gexf/preview.d.ts +77 -0
  160. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  161. package/dist/src/formats/gexf/preview.js +191 -0
  162. package/dist/src/formats/gexf/preview.js.map +1 -0
  163. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  164. package/dist/src/formats/gexf/schema.js +2 -1
  165. package/dist/src/formats/gexf/schema.js.map +1 -1
  166. package/dist/src/formats/gexf/styles.d.ts +58 -31
  167. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  168. package/dist/src/formats/gexf/styles.js +848 -225
  169. package/dist/src/formats/gexf/styles.js.map +1 -1
  170. package/dist/src/formats/gml/importer.d.ts +5 -2
  171. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  172. package/dist/src/formats/gml/importer.js +258 -71
  173. package/dist/src/formats/gml/importer.js.map +1 -1
  174. package/dist/src/formats/gml/index.d.ts +1 -1
  175. package/dist/src/formats/gml/index.d.ts.map +1 -1
  176. package/dist/src/formats/gml/index.js +1 -1
  177. package/dist/src/formats/gml/index.js.map +1 -1
  178. package/dist/src/formats/gml/positions.d.ts +7 -0
  179. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  180. package/dist/src/formats/gml/positions.js +29 -7
  181. package/dist/src/formats/gml/positions.js.map +1 -1
  182. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  183. package/dist/src/formats/gml/styles.js +753 -101
  184. package/dist/src/formats/gml/styles.js.map +1 -1
  185. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  186. package/dist/src/formats/graphml/styles-plain.js +6 -10
  187. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  188. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  189. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  190. package/dist/src/formats/graphml/styles-yed.js +692 -161
  191. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  192. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  193. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  194. package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
  195. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  196. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  197. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/yfiles.js +16 -6
  199. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  200. package/dist/src/formats/json/dialect.d.ts +3 -2
  201. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  202. package/dist/src/formats/json/dialect.js +39 -5
  203. package/dist/src/formats/json/dialect.js.map +1 -1
  204. package/dist/src/formats/json/importer.d.ts +13 -2
  205. package/dist/src/formats/json/importer.d.ts.map +1 -1
  206. package/dist/src/formats/json/importer.js +42 -6
  207. package/dist/src/formats/json/importer.js.map +1 -1
  208. package/dist/src/formats/json/index.d.ts +1 -1
  209. package/dist/src/formats/json/index.d.ts.map +1 -1
  210. package/dist/src/formats/json/index.js +1 -1
  211. package/dist/src/formats/json/index.js.map +1 -1
  212. package/dist/src/formats/json/positions.d.ts +5 -2
  213. package/dist/src/formats/json/positions.d.ts.map +1 -1
  214. package/dist/src/formats/json/positions.js +20 -4
  215. package/dist/src/formats/json/positions.js.map +1 -1
  216. package/dist/src/formats/json/styles.d.ts +12 -1
  217. package/dist/src/formats/json/styles.d.ts.map +1 -1
  218. package/dist/src/formats/json/styles.js +1755 -136
  219. package/dist/src/formats/json/styles.js.map +1 -1
  220. package/dist/src/formats/pajek/draw.d.ts +96 -0
  221. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  222. package/dist/src/formats/pajek/draw.js +372 -0
  223. package/dist/src/formats/pajek/draw.js.map +1 -0
  224. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  225. package/dist/src/formats/pajek/exporter.js +70 -51
  226. package/dist/src/formats/pajek/exporter.js.map +1 -1
  227. package/dist/src/formats/pajek/importer.d.ts +9 -0
  228. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  229. package/dist/src/formats/pajek/importer.js +233 -102
  230. package/dist/src/formats/pajek/importer.js.map +1 -1
  231. package/dist/src/formats/pajek/index.d.ts +1 -0
  232. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  233. package/dist/src/formats/pajek/index.js.map +1 -1
  234. package/dist/src/formats/pajek/styles.d.ts +15 -7
  235. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  236. package/dist/src/formats/pajek/styles.js +1278 -114
  237. package/dist/src/formats/pajek/styles.js.map +1 -1
  238. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  239. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  240. package/dist/src/formats/pajek/syntax.js +26 -2
  241. package/dist/src/formats/pajek/syntax.js.map +1 -1
  242. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  243. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  244. package/dist/src/formats/xgmml/emit.js +65 -5
  245. package/dist/src/formats/xgmml/emit.js.map +1 -1
  246. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  247. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  248. package/dist/src/formats/xgmml/styles.js +277 -60
  249. package/dist/src/formats/xgmml/styles.js.map +1 -1
  250. package/dist/src/index.d.ts +4 -3
  251. package/dist/src/index.d.ts.map +1 -1
  252. package/dist/src/index.js +4 -3
  253. package/dist/src/index.js.map +1 -1
  254. package/dist/src/positions/convert.d.ts.map +1 -1
  255. package/dist/src/positions/convert.js +11 -1
  256. package/dist/src/positions/convert.js.map +1 -1
  257. package/dist/src/positions/extract.d.ts.map +1 -1
  258. package/dist/src/positions/extract.js +53 -1
  259. package/dist/src/positions/extract.js.map +1 -1
  260. package/dist/src/positions/index.d.ts +1 -1
  261. package/dist/src/positions/index.d.ts.map +1 -1
  262. package/dist/src/positions/types.d.ts +59 -0
  263. package/dist/src/positions/types.d.ts.map +1 -1
  264. package/dist/src/sources/builtins.d.ts +1 -1
  265. package/dist/src/sources/builtins.d.ts.map +1 -1
  266. package/dist/src/sources/builtins.js +8 -2
  267. package/dist/src/sources/builtins.js.map +1 -1
  268. package/dist/src/sources/context.d.ts.map +1 -1
  269. package/dist/src/sources/context.js +1 -0
  270. package/dist/src/sources/context.js.map +1 -1
  271. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  272. package/dist/src/sources/cypher/descriptor.js +5 -0
  273. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  274. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  275. package/dist/src/sources/cypher/index.js +124 -18
  276. package/dist/src/sources/cypher/index.js.map +1 -1
  277. package/dist/src/sources/cypher/params.d.ts +1 -1
  278. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  279. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  280. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  281. package/dist/src/sources/cypher/query-builder.js +31 -0
  282. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  283. package/dist/src/sources/ids.d.ts +5 -0
  284. package/dist/src/sources/ids.d.ts.map +1 -1
  285. package/dist/src/sources/ids.js +5 -0
  286. package/dist/src/sources/ids.js.map +1 -1
  287. package/dist/src/sources/params.d.ts +3 -0
  288. package/dist/src/sources/params.d.ts.map +1 -1
  289. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  290. package/dist/src/sources/rest/descriptor.js +5 -0
  291. package/dist/src/sources/rest/descriptor.js.map +1 -1
  292. package/dist/src/sources/rest/source.d.ts.map +1 -1
  293. package/dist/src/sources/rest/source.js +15 -0
  294. package/dist/src/sources/rest/source.js.map +1 -1
  295. package/dist/src/sources/sigv4.d.ts +5 -3
  296. package/dist/src/sources/sigv4.d.ts.map +1 -1
  297. package/dist/src/sources/sigv4.js +6 -4
  298. package/dist/src/sources/sigv4.js.map +1 -1
  299. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  300. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  301. package/dist/src/sources/sparql/descriptor.js +64 -0
  302. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  303. package/dist/src/sources/sparql/index.d.ts +28 -0
  304. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  305. package/dist/src/sources/sparql/index.js +314 -0
  306. package/dist/src/sources/sparql/index.js.map +1 -0
  307. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  308. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  309. package/dist/src/sources/sparql/ntriples.js +180 -0
  310. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  311. package/dist/src/sources/sparql/params.d.ts +27 -0
  312. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  313. package/dist/src/sources/sparql/params.js +5 -0
  314. package/dist/src/sources/sparql/params.js.map +1 -0
  315. package/dist/src/sources/sparql/query.d.ts +72 -0
  316. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  317. package/dist/src/sources/sparql/query.js +113 -0
  318. package/dist/src/sources/sparql/query.js.map +1 -0
  319. package/dist/src/sources/types.d.ts +31 -0
  320. package/dist/src/sources/types.d.ts.map +1 -1
  321. package/dist/src/styles/annotations.d.ts +61 -5
  322. package/dist/src/styles/annotations.d.ts.map +1 -1
  323. package/dist/src/styles/annotations.js +130 -22
  324. package/dist/src/styles/annotations.js.map +1 -1
  325. package/dist/src/styles/canon/bends.d.ts +46 -0
  326. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  327. package/dist/src/styles/canon/bends.js +123 -0
  328. package/dist/src/styles/canon/bends.js.map +1 -1
  329. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  330. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  331. package/dist/src/styles/canon/color-tables.js +10 -4
  332. package/dist/src/styles/canon/color-tables.js.map +1 -1
  333. package/dist/src/styles/canon/color.d.ts +3 -1
  334. package/dist/src/styles/canon/color.d.ts.map +1 -1
  335. package/dist/src/styles/canon/color.js +103 -3
  336. package/dist/src/styles/canon/color.js.map +1 -1
  337. package/dist/src/styles/canon/enums.d.ts +2 -2
  338. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  339. package/dist/src/styles/canon/enums.js +81 -7
  340. package/dist/src/styles/canon/enums.js.map +1 -1
  341. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  342. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  343. package/dist/src/styles/canon/graphviz.js +57 -9
  344. package/dist/src/styles/canon/graphviz.js.map +1 -1
  345. package/dist/src/styles/canon/number.d.ts +8 -0
  346. package/dist/src/styles/canon/number.d.ts.map +1 -1
  347. package/dist/src/styles/canon/number.js +18 -0
  348. package/dist/src/styles/canon/number.js.map +1 -1
  349. package/dist/src/styles/canon/text.d.ts +29 -2
  350. package/dist/src/styles/canon/text.d.ts.map +1 -1
  351. package/dist/src/styles/canon/text.js +156 -16
  352. package/dist/src/styles/canon/text.js.map +1 -1
  353. package/dist/src/styles/codes.d.ts +2 -0
  354. package/dist/src/styles/codes.d.ts.map +1 -1
  355. package/dist/src/styles/codes.js +2 -0
  356. package/dist/src/styles/codes.js.map +1 -1
  357. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  358. package/dist/src/styles/cyjs/cascade.js +1015 -79
  359. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  360. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  361. package/dist/src/styles/cyjs/defaults-table.js +3 -0
  362. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  363. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  364. package/dist/src/styles/cyjs/emit.js +202 -9
  365. package/dist/src/styles/cyjs/emit.js.map +1 -1
  366. package/dist/src/styles/cyjs/face.d.ts +20 -0
  367. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  368. package/dist/src/styles/cyjs/face.js +332 -0
  369. package/dist/src/styles/cyjs/face.js.map +1 -0
  370. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  371. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  372. package/dist/src/styles/cyjs/mappers.js +461 -26
  373. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  374. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  375. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  376. package/dist/src/styles/cyjs/routes.js +360 -0
  377. package/dist/src/styles/cyjs/routes.js.map +1 -0
  378. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  379. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  380. package/dist/src/styles/cytoscape/charts.js +560 -0
  381. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  382. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  383. package/dist/src/styles/cytoscape/emit.js +156 -48
  384. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  385. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  386. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  387. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  388. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  389. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  390. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  391. package/dist/src/styles/cytoscape/mappings.js +92 -0
  392. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  393. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  394. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  395. package/dist/src/styles/cytoscape/resolve.js +623 -17
  396. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  397. package/dist/src/styles/defaults.d.ts +46 -26
  398. package/dist/src/styles/defaults.d.ts.map +1 -1
  399. package/dist/src/styles/defaults.js +308 -71
  400. package/dist/src/styles/defaults.js.map +1 -1
  401. package/dist/src/styles/index.d.ts +4 -3
  402. package/dist/src/styles/index.d.ts.map +1 -1
  403. package/dist/src/styles/index.js +3 -2
  404. package/dist/src/styles/index.js.map +1 -1
  405. package/dist/src/styles/internal.d.ts +1 -0
  406. package/dist/src/styles/internal.d.ts.map +1 -1
  407. package/dist/src/styles/internal.js +1 -0
  408. package/dist/src/styles/internal.js.map +1 -1
  409. package/dist/src/styles/io/generic.d.ts.map +1 -1
  410. package/dist/src/styles/io/generic.js +56 -16
  411. package/dist/src/styles/io/generic.js.map +1 -1
  412. package/dist/src/styles/io/round-trip.d.ts +56 -0
  413. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  414. package/dist/src/styles/io/round-trip.js +138 -0
  415. package/dist/src/styles/io/round-trip.js.map +1 -0
  416. package/dist/src/styles/io/writer.d.ts.map +1 -1
  417. package/dist/src/styles/io/writer.js +6 -1
  418. package/dist/src/styles/io/writer.js.map +1 -1
  419. package/dist/src/styles/notes.d.ts.map +1 -1
  420. package/dist/src/styles/notes.js +1 -0
  421. package/dist/src/styles/notes.js.map +1 -1
  422. package/dist/src/styles/plan/features.d.ts +1 -1
  423. package/dist/src/styles/plan/features.d.ts.map +1 -1
  424. package/dist/src/styles/plan/features.js +22 -2
  425. package/dist/src/styles/plan/features.js.map +1 -1
  426. package/dist/src/styles/plan/index.d.ts +1 -1
  427. package/dist/src/styles/plan/index.d.ts.map +1 -1
  428. package/dist/src/styles/plan/index.js +1 -1
  429. package/dist/src/styles/plan/index.js.map +1 -1
  430. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  431. package/dist/src/styles/plan/plan.js +61 -4
  432. package/dist/src/styles/plan/plan.js.map +1 -1
  433. package/dist/src/styles/plan/resolve.d.ts +11 -0
  434. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  435. package/dist/src/styles/plan/resolve.js +40 -4
  436. package/dist/src/styles/plan/resolve.js.map +1 -1
  437. package/dist/src/styles/slots.d.ts +14 -0
  438. package/dist/src/styles/slots.d.ts.map +1 -0
  439. package/dist/src/styles/slots.js +20 -0
  440. package/dist/src/styles/slots.js.map +1 -0
  441. package/dist/src/styles/types.d.ts +622 -6
  442. package/dist/src/styles/types.d.ts.map +1 -1
  443. package/dist/src/styles/vocabulary.d.ts +3 -2
  444. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  445. package/dist/src/styles/vocabulary.js +203 -0
  446. package/dist/src/styles/vocabulary.js.map +1 -1
  447. package/dist/styles.js +30 -239
  448. package/dist/styles.js.map +1 -1
  449. package/dist/xgmml.js +3 -3
  450. package/package.json +27 -7
  451. package/src/formats/cx/importer.ts +6 -1
  452. package/src/formats/cx/styles.ts +143 -9
  453. package/src/formats/cx2/importer.ts +1 -0
  454. package/src/formats/cx2/styles.ts +3 -1
  455. package/src/formats/cys/importer.ts +1 -0
  456. package/src/formats/cys/styles.ts +27 -5
  457. package/src/formats/dot/drawing.ts +799 -0
  458. package/src/formats/dot/importer.ts +120 -35
  459. package/src/formats/dot/label-places.ts +228 -0
  460. package/src/formats/dot/record.ts +336 -0
  461. package/src/formats/dot/styles.ts +1654 -153
  462. package/src/formats/gexf/dialog-metrics.ts +61 -0
  463. package/src/formats/gexf/importer.ts +50 -5
  464. package/src/formats/gexf/preview.ts +217 -0
  465. package/src/formats/gexf/schema.ts +2 -1
  466. package/src/formats/gexf/styles.ts +1099 -245
  467. package/src/formats/gml/importer.ts +291 -76
  468. package/src/formats/gml/index.ts +1 -1
  469. package/src/formats/gml/positions.ts +29 -7
  470. package/src/formats/gml/styles.ts +851 -109
  471. package/src/formats/graphml/styles-plain.ts +6 -15
  472. package/src/formats/graphml/styles-yed.ts +762 -173
  473. package/src/formats/graphml/styles-yfiles3.ts +485 -63
  474. package/src/formats/graphml/yfiles.ts +19 -6
  475. package/src/formats/json/dialect.ts +41 -5
  476. package/src/formats/json/importer.ts +59 -7
  477. package/src/formats/json/index.ts +1 -0
  478. package/src/formats/json/positions.ts +22 -5
  479. package/src/formats/json/styles.ts +2041 -185
  480. package/src/formats/pajek/draw.ts +458 -0
  481. package/src/formats/pajek/exporter.ts +81 -49
  482. package/src/formats/pajek/importer.ts +278 -103
  483. package/src/formats/pajek/index.ts +1 -0
  484. package/src/formats/pajek/styles.ts +1381 -133
  485. package/src/formats/pajek/syntax.ts +27 -2
  486. package/src/formats/xgmml/emit.ts +73 -5
  487. package/src/formats/xgmml/styles.ts +330 -71
  488. package/src/index.ts +5 -1
  489. package/src/positions/convert.ts +12 -1
  490. package/src/positions/extract.ts +55 -1
  491. package/src/positions/index.ts +1 -0
  492. package/src/positions/types.ts +60 -0
  493. package/src/sources/builtins.ts +8 -1
  494. package/src/sources/context.ts +1 -0
  495. package/src/sources/cypher/descriptor.ts +7 -1
  496. package/src/sources/cypher/index.ts +148 -18
  497. package/src/sources/cypher/params.ts +1 -1
  498. package/src/sources/cypher/query-builder.ts +33 -0
  499. package/src/sources/ids.ts +6 -0
  500. package/src/sources/params.ts +3 -0
  501. package/src/sources/rest/descriptor.ts +5 -0
  502. package/src/sources/rest/source.ts +16 -0
  503. package/src/sources/sigv4.ts +6 -4
  504. package/src/sources/sparql/descriptor.ts +67 -0
  505. package/src/sources/sparql/index.ts +356 -0
  506. package/src/sources/sparql/ntriples.ts +219 -0
  507. package/src/sources/sparql/params.ts +28 -0
  508. package/src/sources/sparql/query.ts +162 -0
  509. package/src/sources/types.ts +35 -0
  510. package/src/styles/annotations.ts +201 -27
  511. package/src/styles/canon/bends.ts +137 -0
  512. package/src/styles/canon/color-tables.ts +10 -4
  513. package/src/styles/canon/color.ts +105 -3
  514. package/src/styles/canon/enums.ts +98 -8
  515. package/src/styles/canon/graphviz.ts +71 -10
  516. package/src/styles/canon/number.ts +19 -0
  517. package/src/styles/canon/text.ts +187 -16
  518. package/src/styles/codes.ts +2 -0
  519. package/src/styles/cyjs/cascade.ts +1160 -84
  520. package/src/styles/cyjs/defaults-table.ts +3 -0
  521. package/src/styles/cyjs/emit.ts +233 -13
  522. package/src/styles/cyjs/face.ts +372 -0
  523. package/src/styles/cyjs/mappers.ts +492 -27
  524. package/src/styles/cyjs/routes.ts +432 -0
  525. package/src/styles/cytoscape/charts.ts +684 -0
  526. package/src/styles/cytoscape/emit.ts +170 -48
  527. package/src/styles/cytoscape/lexicon.ts +431 -78
  528. package/src/styles/cytoscape/mappings.ts +108 -0
  529. package/src/styles/cytoscape/resolve.ts +741 -17
  530. package/src/styles/defaults.ts +417 -108
  531. package/src/styles/index.ts +5 -0
  532. package/src/styles/internal.ts +1 -0
  533. package/src/styles/io/generic.ts +79 -23
  534. package/src/styles/io/round-trip.ts +202 -0
  535. package/src/styles/io/writer.ts +6 -1
  536. package/src/styles/notes.ts +1 -0
  537. package/src/styles/plan/features.ts +23 -2
  538. package/src/styles/plan/index.ts +1 -1
  539. package/src/styles/plan/plan.ts +69 -5
  540. package/src/styles/plan/resolve.ts +47 -4
  541. package/src/styles/slots.ts +25 -0
  542. package/src/styles/types.ts +633 -5
  543. package/src/styles/vocabulary.ts +211 -2
  544. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  545. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  546. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  547. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  548. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  549. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  550. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  551. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  552. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  553. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  554. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  555. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  556. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  557. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  558. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  559. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  560. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  561. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  562. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  563. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  564. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  565. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  566. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  567. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  568. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  569. package/dist/chunks/writer-DvHTl36J.js +0 -449
  570. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -1,15 +1,269 @@
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-iptrlMBb.js";
11
+ import { S as StyleApproximations } from "./approximations-Bzn3L-je.js";
12
+ import { e as elementValues, t as takeFromBlock } from "./round-trip-Zm3_ivgq.js";
13
+ import { v as valueColumns } from "./styles-yed-UMFdNqze.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 iniNumber(draw, name) {
63
+ const v = draw.ini.get(name);
64
+ const n = v === void 0 || v.trim() === "" ? Number.NaN : Number(v);
65
+ return Number.isFinite(n) ? n : null;
66
+ }
67
+ const PARTITION_COLORS = [
68
+ "#00ffff",
69
+ "#ffff00",
70
+ "#7fff00",
71
+ "#ff0000",
72
+ "#0000ff",
73
+ "#ffd8f2",
74
+ "#ffffff",
75
+ "#ff6321",
76
+ "#8c23ff",
77
+ "#606dc4",
78
+ "#1ef9a3",
79
+ "#009900",
80
+ "#7f7f7f",
81
+ "#000000",
82
+ "#ad0000",
83
+ "#ccffb2",
84
+ "#ffff99",
85
+ "#ff00ff",
86
+ "#007091",
87
+ "#ffb528",
88
+ "#ff0a9b",
89
+ "#00e000",
90
+ "#ff779e",
91
+ "#d8f2ff",
92
+ "#d8ff4f",
93
+ "#ff84ff",
94
+ "#e5ffcc",
95
+ "#ccccff",
96
+ "#59ddff",
97
+ "#ffd9bc",
98
+ "#db9370",
99
+ "#ccffff",
100
+ "#d8d8d8",
101
+ "#666666",
102
+ "#a5a5a5",
103
+ "#3f3f3f",
104
+ "#e5e5e5",
105
+ "#262626",
106
+ "#bfbfbf",
107
+ "#595959"
108
+ ];
109
+ const VERTEX_SIZE = 20;
110
+ const VERTEX_FILL = "#ffd9bc";
111
+ const SIZE_OF_VERTICES = 8;
112
+ function objectValues(snapshot, kind, n) {
113
+ if (n < 1) {
114
+ return null;
115
+ }
116
+ const pajek = snapshot.meta.extra.pajek;
117
+ const name = pajek?.objects?.filter((o) => o.kind === kind)[n - 1]?.column;
118
+ if (name === void 0 || !snapshot.nodes.has(name)) {
119
+ return null;
120
+ }
121
+ return (i) => {
122
+ const v = snapshot.nodes.value(name, i);
123
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
124
+ };
125
+ }
126
+ function column(values, property, n) {
127
+ values[property] ??= new Array(n).fill(null);
128
+ return values[property];
129
+ }
130
+ function drawVertices(draw, snapshot, node) {
131
+ const n = snapshot.nodeCount;
132
+ const width = column(node, "width", n);
133
+ const height = column(node, "height", n);
134
+ scaleVertexSizes(draw, width, height);
135
+ sizeByVectors(draw, snapshot, width, height);
136
+ colorByPartition(draw, snapshot, node);
137
+ const opacity = iniNumber(draw, "TransparencyofVertices");
138
+ if (opacity !== null && opacity < 1) {
139
+ const o = Math.max(0, opacity);
140
+ const fill = column(node, "fillOpacity", n);
141
+ fill.forEach((v, i) => {
142
+ fill[i] = (typeof v === "number" ? v : 1) * o;
143
+ });
144
+ column(node, "borderOpacity", n).fill(o * o);
145
+ }
146
+ if (flag(draw, "Form10.effect3d")) {
147
+ effect3d(snapshot, node);
148
+ }
149
+ markVertices(draw, node, n);
150
+ for (const property of ["width", "height"]) {
151
+ if (node[property].every((v) => v === null)) {
152
+ Reflect.deleteProperty(node, property);
153
+ }
154
+ }
155
+ }
156
+ function scaleVertexSizes(draw, width, height) {
157
+ const size = iniNumber(draw, "Form8.SizeofVertices");
158
+ if (size === null || size === SIZE_OF_VERTICES) {
159
+ return;
160
+ }
161
+ const f = size / SIZE_OF_VERTICES;
162
+ const scaled = (v) => typeof v === "number" ? v * f : VERTEX_SIZE * f * f;
163
+ for (let i = 0; i < width.length; i++) {
164
+ width[i] = scaled(width[i]);
165
+ height[i] = scaled(height[i]);
166
+ }
167
+ }
168
+ function colorByPartition(draw, snapshot, node) {
169
+ const partition = objectValues(snapshot, "partition", draw.partition);
170
+ if (partition === null) {
171
+ return;
172
+ }
173
+ const fill = column(node, "fill", snapshot.nodeCount);
174
+ for (let i = 0; i < snapshot.nodeCount; i++) {
175
+ const k = partition(i);
176
+ if (k !== null) {
177
+ fill[i] = PARTITION_COLORS[Math.abs(k) % PARTITION_COLORS.length];
178
+ }
179
+ }
180
+ }
181
+ function markVertices(draw, node, n) {
182
+ const mark = iniNumber(draw, "Form8.MarkVerticesUsing");
183
+ if (mark === 2) {
184
+ column(node, "label", n).forEach((_, i, a) => {
185
+ a[i] = String(i + 1);
186
+ });
187
+ } else if (mark === 3 || mark === 4) {
188
+ column(node, "label", n).fill("");
189
+ }
190
+ }
191
+ function effect3d(snapshot, node) {
192
+ const n = snapshot.nodeCount;
193
+ const fill = column(node, "fill", n);
194
+ const end = column(node, "fillGradient", n);
195
+ const angle = column(node, "fillGradientAngle", n);
196
+ const half = (v) => {
197
+ const h = v / 2;
198
+ const f = Math.floor(h);
199
+ return h - f === 0.5 && f % 2 === 0 ? f : Math.round(h);
200
+ };
201
+ for (let i = 0; i < n; i++) {
202
+ const color = typeof fill[i] === "string" ? String(fill[i]) : VERTEX_FILL;
203
+ end[i] = `#${[1, 3, 5].map(
204
+ (k) => half(Number.parseInt(color.slice(k, k + 2), 16)).toString(16).padStart(2, "0")
205
+ ).join("")}`;
206
+ const phi = snapshot.nodes.has("phi") ? Number(snapshot.nodes.value("phi", i)) : 0;
207
+ angle[i] = Number.isFinite(phi) ? ((90 - phi) % 360 + 360) % 360 : 90;
208
+ }
209
+ }
210
+ function sizeByVectors(draw, snapshot, width, height) {
211
+ const first = objectValues(snapshot, "vector", draw.vector);
212
+ if (first === null) {
213
+ return;
214
+ }
215
+ const second = objectValues(snapshot, "vector", draw.vector2);
216
+ const scale = (sizes, i, v) => {
217
+ if (v !== null && v >= 0) {
218
+ sizes[i] = (typeof sizes[i] === "number" ? sizes[i] : VERTEX_SIZE) * v;
219
+ }
220
+ };
221
+ for (let i = 0; i < snapshot.nodeCount; i++) {
222
+ const v = first(i);
223
+ if (second === null) {
224
+ const root = v === null || v < 0 ? null : Math.sqrt(v);
225
+ scale(width, i, root);
226
+ scale(height, i, root);
227
+ } else {
228
+ scale(width, i, v);
229
+ scale(height, i, second(i));
230
+ }
231
+ }
232
+ }
233
+ function drawLines(draw, snapshot, node, edge) {
234
+ const m = snapshot.edgeCount;
235
+ const opacity = iniNumber(draw, "TransparencyofLines");
236
+ if (opacity !== null && opacity < 1) {
237
+ const o = column(edge, "opacity", m);
238
+ o.forEach((v, e) => {
239
+ o[e] = (typeof v === "number" ? v : 1) * Math.max(0, opacity);
240
+ });
241
+ }
242
+ if (flag(draw, "Form10.StraightLinesOnly1")) {
243
+ const curved = column(edge, "curved", m);
244
+ for (let e = 0; e < m; e++) {
245
+ const bends = edge.bends?.[e];
246
+ if (bends === null || bends === void 0) {
247
+ curved[e] = false;
248
+ }
249
+ }
250
+ }
251
+ if (flag(draw, "Form10.ColorGradientLines")) {
252
+ const fill = node.fill;
253
+ const fillOf = (i) => typeof fill?.[i] === "string" ? fill[i] : VERTEX_FILL;
254
+ const colors = column(edge, "gradientColors", m);
255
+ const kind = column(edge, "gradientKind", m);
256
+ const sourceArrow = column(edge, "sourceArrowColor", m);
257
+ const targetArrow = column(edge, "targetArrowColor", m);
258
+ for (let e = 0; e < m; e++) {
259
+ const [s, t] = [fillOf(snapshot.edgeSource(e)), fillOf(snapshot.edgeTarget(e))];
260
+ colors[e] = `${s} ${t}`;
261
+ kind[e] = "linear";
262
+ sourceArrow[e] = s;
263
+ targetArrow[e] = t;
264
+ }
265
+ }
266
+ }
13
267
  const LABEL_COLUMN = "label";
14
268
  const POSITION_COLUMN = "position";
15
269
  const SHAPE_COLUMN = "shape";
@@ -256,7 +510,7 @@ function parseIntervals(token) {
256
510
  return [];
257
511
  }
258
512
  const spells = [];
259
- for (const part of body.split(",")) {
513
+ for (const part of body.split(/[,/]/)) {
260
514
  spells.push(parseSpell(token, part));
261
515
  }
262
516
  return spells;
@@ -328,6 +582,20 @@ function isParameterKey(text) {
328
582
  }
329
583
  return !/^[+-]?(\.\d|\d)/.test(text) && !/^[+-]?(?:nan|inf|infinity)$/i.test(text);
330
584
  }
585
+ const VOIDING_KEYS = /* @__PURE__ */ new Set([
586
+ "bc",
587
+ "bw",
588
+ "s_size",
589
+ "phi",
590
+ "r",
591
+ "q",
592
+ "lc",
593
+ "la",
594
+ "lr",
595
+ "lphi",
596
+ "fos",
597
+ "font"
598
+ ]);
331
599
  const PAJEK_STYLE_CAPABILITIES = Object.freeze({
332
600
  tool: "pajek",
333
601
  node: Object.freeze([
@@ -338,22 +606,93 @@ const PAJEK_STYLE_CAPABILITIES = Object.freeze({
338
606
  "borderColor",
339
607
  "borderWidth",
340
608
  "shape",
609
+ "shapePoints",
341
610
  "width",
342
611
  "height",
343
612
  "labelColor",
344
- "labelSize"
613
+ "labelSize",
614
+ "labelFont",
615
+ "labelPosition",
616
+ "labelOffsetX",
617
+ "labelOffsetY",
618
+ "labelShiftX"
619
+ ]),
620
+ edge: Object.freeze([
621
+ "color",
622
+ "opacity",
623
+ "width",
624
+ "lineStyle",
625
+ "sourceArrow",
626
+ "targetArrow",
627
+ "arrowPosition",
628
+ "label",
629
+ "labelColor",
630
+ "labelSize",
631
+ "labelFont"
345
632
  ]),
346
- edge: Object.freeze(["color", "opacity", "width", "lineStyle", "sourceArrow", "targetArrow"]),
347
633
  block: "native"
348
634
  });
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"];
635
+ const PAJEK_VERTEX_SIZE = 20;
636
+ const PAJEK_FIGURES = /* @__PURE__ */ new Map([
637
+ ["other:man", [2.502, 6.487]],
638
+ ["other:woman", [3.003, 6.478]]
639
+ ]);
640
+ const PAJEK_POINTS_PER_UNIT = 500;
641
+ const NODE_KEYS = [
642
+ "ic",
643
+ "bc",
644
+ "bw",
645
+ "s_size",
646
+ "x_fact",
647
+ "y_fact",
648
+ "phi",
649
+ "q",
650
+ "lc",
651
+ "fos",
652
+ "font",
653
+ "lr",
654
+ "lphi",
655
+ "la"
656
+ ];
657
+ const EDGE_KEYS = ["c", "w", "p", "s", "ap", "l", "lc", "fos", "font"];
658
+ const CARRIED = {
659
+ node: [SHAPE_COLUMN, ...NODE_KEYS],
660
+ edge: ["c", "w", "p", "s", "ap"]
661
+ };
662
+ const CARRIED_LINE = CARRIED.edge.filter((key) => key !== "p");
663
+ const EDGE_WIDTH_PER_W = 2;
664
+ const ARC_DEFAULTS = { color: "#999999", width: 1 };
665
+ function carriedParams(keys, whole) {
666
+ let last = /* @__PURE__ */ new Map();
667
+ return (get) => {
668
+ const own = /* @__PURE__ */ new Map();
669
+ for (const key of keys) {
670
+ const v = get(key);
671
+ if (v !== null) {
672
+ own.set(key, v);
673
+ }
674
+ }
675
+ if (whole) {
676
+ if (own.size > 0) {
677
+ last = own;
678
+ return get;
679
+ }
680
+ } else {
681
+ for (const [key, v] of own) {
682
+ last.set(key, v);
683
+ }
684
+ }
685
+ const carried = last;
686
+ return (key) => get(key) ?? (keys.includes(key) ? carried.get(key) ?? null : null);
687
+ };
688
+ }
352
689
  const DIRECTED_KEY = "directed";
353
690
  const READ = {
354
691
  node: [
355
692
  "label",
356
693
  "shape",
694
+ "shapePoints",
695
+ "shapePointsStretch",
357
696
  "fill",
358
697
  "fillOpacity",
359
698
  "borderColor",
@@ -361,9 +700,26 @@ const READ = {
361
700
  "width",
362
701
  "height",
363
702
  "labelColor",
364
- "labelSize"
703
+ "labelSize",
704
+ "labelFont",
705
+ "labelPosition",
706
+ "labelOffsetX",
707
+ "labelOffsetY",
708
+ "labelShiftX",
709
+ "labelRotation"
365
710
  ],
366
- edge: ["color", "opacity", "width", "lineStyle"]
711
+ edge: [
712
+ "color",
713
+ "opacity",
714
+ "width",
715
+ "lineStyle",
716
+ "arrowSize",
717
+ "arrowPosition",
718
+ "label",
719
+ "labelColor",
720
+ "labelSize",
721
+ "labelFont"
722
+ ]
367
723
  };
368
724
  function readColor(raw, property, opacity, put, at) {
369
725
  if (raw === null) {
@@ -371,6 +727,10 @@ function readColor(raw, property, opacity, put, at) {
371
727
  }
372
728
  const c = canonColor(raw, "dvips", at(property));
373
729
  if (c === null) {
730
+ const unknown = UNKNOWN_COLORS.get(property);
731
+ if (unknown !== void 0 && typeof raw === "string" && /^[A-Za-z]\w*$/.test(raw.trim())) {
732
+ put(property, unknown);
733
+ }
374
734
  return;
375
735
  }
376
736
  put(property, c.color);
@@ -379,43 +739,437 @@ function readColor(raw, property, opacity, put, at) {
379
739
  put(opacity, alpha);
380
740
  }
381
741
  }
742
+ const UNKNOWN_COLORS = /* @__PURE__ */ new Map([
743
+ ["fill", "#ffffff"],
744
+ ["color", "#000000"]
745
+ ]);
382
746
  function readNumber(raw, property, put, at) {
383
747
  if (raw !== null) {
384
748
  put(property, canonNumber(raw, at(property)));
385
749
  }
386
750
  }
387
- function readVertex(get, put, at) {
751
+ function readVertex(get, put, at, place = null) {
388
752
  const label = get(LABEL_COLUMN);
389
753
  if (label !== null && label !== "") {
390
754
  put("label", canonText(label, at("label")));
391
755
  }
392
- const shape = get(SHAPE_COLUMN);
393
- if (shape !== null) {
394
- put("shape", canonEnum("shape", shape, "dvips", at("shape")));
756
+ const raw = get(SHAPE_COLUMN);
757
+ const shape = raw === null ? null : canonEnum("shape", raw, "dvips", at("shape"));
758
+ if (raw !== null) {
759
+ put("shape", shape);
395
760
  }
396
761
  readColor(get("ic"), "fill", "fillOpacity", put, at);
397
762
  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);
763
+ readNumber(get("bw"), "borderWidth", put, at);
764
+ readSize(get, put, at, PAJEK_FIGURES.get(String(shape)));
765
+ readOutline(get, put, shape);
405
766
  readColor(get("lc"), "labelColor", null, put, at);
406
767
  readNumber(get("fos"), "labelSize", put, at);
768
+ readFont(get("font"), put, at);
769
+ readLabelPosition(get, put, at);
770
+ readLabelAngle(get("la"), put, at, place);
771
+ if (shape === "none") {
772
+ for (const [property, value] of EMPTY_LABEL) {
773
+ put(property, value);
774
+ }
775
+ }
776
+ }
777
+ const PAJEK_OUTLINES = /* @__PURE__ */ new Map([
778
+ [
779
+ "rectangle",
780
+ [
781
+ [-1, 1],
782
+ [1, 1],
783
+ [1, -1],
784
+ [-1, -1]
785
+ ]
786
+ ],
787
+ [
788
+ "triangle",
789
+ [
790
+ [1, -1],
791
+ [0, 1],
792
+ [-1, -1]
793
+ ]
794
+ ],
795
+ [
796
+ "other:house",
797
+ [
798
+ [-0.7, -1],
799
+ [0.7, -1],
800
+ [0.7, 0.3],
801
+ [1, 0.3],
802
+ [1, 0.4],
803
+ [0, 1],
804
+ [-1, 0.4],
805
+ [-1, 0.3],
806
+ [-0.7, 0.3]
807
+ ]
808
+ ]
809
+ ]);
810
+ const PAJEK_DIAMOND_Q = 1e-3;
811
+ function readOutline(get, put, shape) {
812
+ const phi = numberOrNull(get("phi")) ?? 0;
813
+ const q = numberOrNull(get("q")) ?? PAJEK_DIAMOND_Q;
814
+ const diamond = [
815
+ [-1, 0],
816
+ [-q, 1],
817
+ [q, 1],
818
+ [1, 0],
819
+ [q, -1],
820
+ [-q, -1]
821
+ ];
822
+ const corners = shape === "diamond" ? diamond : PAJEK_OUTLINES.get(String(shape));
823
+ if (corners === void 0 || shape !== "diamond" && phi % 360 === 0) {
824
+ return;
825
+ }
826
+ const [w, h] = [numberOrNull(get("x_fact")) || 1, numberOrNull(get("y_fact")) || 1];
827
+ const [c, s] = [Math.cos(phi * Math.PI / 180), Math.sin(phi * Math.PI / 180)];
828
+ const round = (v) => String(Number(v.toFixed(4)) + 0);
829
+ const points = corners.map(([x, y]) => {
830
+ const [px, py] = [x * w, y * h];
831
+ return `${round((px * c - py * s) / w)},${round((px * s + py * c) / h)}`;
832
+ });
833
+ put("shape", "polygon");
834
+ put("shapePoints", points.join(" "));
835
+ put("shapePointsStretch", false);
836
+ }
837
+ const EMPTY_LABEL = [
838
+ ["labelSize", 1],
839
+ ["labelColor", "#ffffff"],
840
+ ["labelPosition", "center"],
841
+ ["labelOffsetX", 0],
842
+ ["labelOffsetY", 0],
843
+ ["labelShiftX", 0]
844
+ ];
845
+ function readFont(raw, put, at) {
846
+ if (raw === null || raw === "") {
847
+ return;
848
+ }
849
+ const ps = typeof raw === "string" ? postscriptFont(raw.trim()) : null;
850
+ if (ps === null) {
851
+ readText(raw, "labelFont", put, at);
852
+ return;
853
+ }
854
+ put("labelFont", ps.family);
407
855
  }
408
- function readLine(get, put, at) {
856
+ function readLabelAngle(raw, put, at, place) {
857
+ let a = raw === null ? null : canonNumber(raw, at("labelRotation"));
858
+ if (a !== null && a >= 360) {
859
+ a = place === null ? null : Math.atan2(0.5 - place[1], place[0] - 0.5) * 180 / Math.PI + a - 360;
860
+ }
861
+ if (a !== null) {
862
+ put("labelRotation", Number((((360 - a) % 360 + 360) % 360).toPrecision(12)));
863
+ }
864
+ }
865
+ function readSize(get, put, at, figure) {
866
+ for (const [key, property, k] of [
867
+ ["x_fact", "width", 0],
868
+ ["y_fact", "height", 1]
869
+ ]) {
870
+ const f = get(key);
871
+ if (f === null && figure === void 0) {
872
+ continue;
873
+ }
874
+ const factor = f === null ? 1 : canonNumber(f, at(property));
875
+ const over = figure?.[k] ?? 1;
876
+ put(property, factor === null ? null : Number((PAJEK_VERTEX_SIZE * factor * over).toPrecision(15)));
877
+ }
878
+ }
879
+ function readText(raw, property, put, at) {
880
+ if (raw !== null && raw !== "") {
881
+ put(property, canonText(raw, at(property)));
882
+ }
883
+ }
884
+ const SIDE_ANGLES = /* @__PURE__ */ new Map([
885
+ ["right", 0],
886
+ ["top-right", 90],
887
+ ["left", 180],
888
+ ["bottom-right", 285]
889
+ ]);
890
+ const NEAREST_SIDES = /* @__PURE__ */ new Map([
891
+ ["top", "top-right"],
892
+ ["top-left", "top-right"],
893
+ ["bottom", "bottom-right"],
894
+ ["bottom-left", "bottom-right"]
895
+ ]);
896
+ function readLabelPosition(get, put, at) {
897
+ const [lr, lphi, fos] = [get("lr"), get("lphi"), get("fos")];
898
+ if (lr === null && lphi === null && fos === null) {
899
+ return;
900
+ }
901
+ const radius = lr === null ? PAJEK_LABEL_RADIUS : canonNumber(lr, at("labelPosition"));
902
+ const angle = lphi === null ? PAJEK_LABEL_ANGLE : canonNumber(lphi, at("labelPosition"));
903
+ const size = fos === null ? PAJEK_LABEL_SIZE : canonNumber(fos, at("labelSize"));
904
+ if (radius === null || angle === null || size === null) {
905
+ return;
906
+ }
907
+ const [x, y] = labelOffset(radius, angle, size);
908
+ put("labelPosition", "center");
909
+ put("labelOffsetX", x);
910
+ put("labelOffsetY", y);
911
+ put("labelShiftX", radius === 0 ? 0 : 0.5);
912
+ }
913
+ function labelOffset(radius, angle, size) {
914
+ if (radius === 0) {
915
+ return [0, 0];
916
+ }
917
+ const t = angle * Math.PI / 180;
918
+ const round = (v) => Number(v.toFixed(9)) + 0;
919
+ return [round(radius * Math.cos(t)), round(-radius * Math.sin(t) - PAJEK_BASELINE_TO_MIDDLE * size)];
920
+ }
921
+ const PAJEK_LABEL_RADIUS = 20;
922
+ const PAJEK_LABEL_ANGLE = 285;
923
+ const PAJEK_LABEL_SIZE = 15;
924
+ const PAJEK_BASELINE_TO_MIDDLE = 0.3465;
925
+ function readLine(get, put, at, directed, labels = true, run = null, loop = null) {
409
926
  readColor(get("c"), "color", "opacity", put, at);
410
- readNumber(get("w"), "width", put, at);
927
+ readNumber(
928
+ get("w"),
929
+ "width",
930
+ (property, value) => {
931
+ put(property, typeof value === "number" && !directed ? value * EDGE_WIDTH_PER_W : value);
932
+ },
933
+ at
934
+ );
411
935
  const p = get("p");
412
- if (p !== null) {
413
- put("lineStyle", canonEnum("lineStyle", p, "dvips", at("lineStyle")));
936
+ if (p === "Dots") {
937
+ put("lineStyle", pajekDash(get, directed));
938
+ } else if (p === "Solid") {
939
+ put("lineStyle", "solid");
940
+ } else if (p !== null) {
941
+ noteAt(at("lineStyle"), STYLE_ISSUE.UNKNOWN_VALUE, typeof p === "string" ? p : JSON.stringify(p));
942
+ put("lineStyle", "solid");
943
+ }
944
+ readNumber(get("s"), "arrowSize", put, at);
945
+ readArrowPosition(get("ap"), put, at);
946
+ const line = loop === null ? get : loopParam(get);
947
+ const controls = loop === null ? null : readLoop(line, put, loop);
948
+ if (labels) {
949
+ readText(get("l"), "label", put, at);
950
+ if (controls === null) {
951
+ readLineLabelPlace(get, put, at, run);
952
+ } else {
953
+ readLineLabelPlace(line, put, at, [PAJEK_POINTS_PER_UNIT, 0], loopTop(controls));
954
+ }
955
+ }
956
+ if (loop === null) {
957
+ readBezier(get, put, run);
958
+ }
959
+ readColor(get("lc"), "labelColor", null, put, at);
960
+ readNumber(get("fos"), "labelSize", put, at);
961
+ readFont(get("font"), put, at);
962
+ }
963
+ const LOOP_DEFAULTS = { a1: -70, k1: 0.3, a2: -70, k2: 0.3 };
964
+ function loopParam(get) {
965
+ return (key) => get(key) ?? (key in LOOP_DEFAULTS ? LOOP_DEFAULTS[key] : null);
966
+ }
967
+ function readLoop(get, put, loop) {
968
+ const run = [PAJEK_POINTS_PER_UNIT, 0];
969
+ const controls = bezierControls(get, run);
970
+ if (controls === null) {
971
+ return null;
972
+ }
973
+ const [[a1, l1], [a2, l2]] = controls;
974
+ const L = PAJEK_POINTS_PER_UNIT;
975
+ const [c1, c2] = [
976
+ [a1 * L, -l1 * L],
977
+ [(a2 - 1) * L, -l2 * L]
978
+ ];
979
+ loop([c1, c2]);
980
+ put("curved", true);
981
+ put("bendCurve", "bezier");
982
+ put("targetArrow", "none");
983
+ return [c1, c2];
984
+ }
985
+ function loopTop(controls) {
986
+ const [c1, c2] = controls;
987
+ return Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI;
988
+ }
989
+ function layLoops(snapshot, loops, node, edge) {
990
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
991
+ for (const [e, controls] of loops) {
992
+ const v = snapshot.edgeSource(e);
993
+ const half = (property) => {
994
+ const size = node[property]?.[v];
995
+ return (typeof size === "number" && size > 0 ? size : PAJEK_VERTEX_SIZE) / 2;
996
+ };
997
+ const [hw, hh] = [half("width"), half("height")];
998
+ const column2 = (property) => edge[property] ??= new Array(snapshot.edgeCount).fill(null);
999
+ column2("bends")[e] = controls.map(([x, y]) => `${fraction(x / hw)},${fraction(-y / hh)}`).join(" ");
1000
+ column2("curved")[e] = true;
1001
+ column2("bendCurve")[e] = "bezier";
1002
+ }
1003
+ }
1004
+ function readLineLabelPlace(get, put, at, run, direction) {
1005
+ const length = run === null ? 0 : Math.hypot(run[0], run[1]);
1006
+ if (run === null || length === 0) {
1007
+ return;
1008
+ }
1009
+ const n = (key, fallback, property) => {
1010
+ const v = get(key);
1011
+ return v === null ? fallback : canonNumber(v, at(property));
1012
+ };
1013
+ const [lp, lr, lphi, la] = [
1014
+ n("lp", 0.5, "labelOffsetX"),
1015
+ n("lr", 0, "labelOffsetX"),
1016
+ n("lphi", 0, "labelOffsetX"),
1017
+ n("la", 0, "labelRotation")
1018
+ ];
1019
+ const size = n("fos", PAJEK_LABEL_SIZE, "labelSize");
1020
+ if (lp === null || lr === null || lphi === null || la === null || size === null) {
1021
+ return;
1022
+ }
1023
+ const along = 0.5 - (lp <= 1 ? lp : lp / length);
1024
+ const t = lphi * Math.PI / 180;
1025
+ const round = (v) => Number(v.toFixed(9)) + 0;
1026
+ const turn = ((direction ?? lineDirection(get, run, along + 0.5)) - la) % 360 + 360;
1027
+ const up = turn * Math.PI / 180;
1028
+ const rise = PAJEK_BASELINE_TO_MIDDLE * size;
1029
+ put("labelPosition", "center");
1030
+ put("labelOffsetX", round(along * run[0] + lr * Math.cos(t) + rise * Math.sin(up)));
1031
+ put("labelOffsetY", round(along * run[1] - lr * Math.sin(t) - rise * Math.cos(up)));
1032
+ put("labelRotation", round(turn % 360));
1033
+ }
1034
+ function readBezier(get, put, run) {
1035
+ const controls = bezierControls(get, run);
1036
+ if (controls === null) {
1037
+ return;
1038
+ }
1039
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
1040
+ put("curved", true);
1041
+ put("bendCurve", "bezier");
1042
+ put("bends", controls.map(([along, across]) => `${fraction(along)},${fraction(across)}`).join(" "));
1043
+ }
1044
+ function readArcEnd(get, put, run, target) {
1045
+ const ap = numberOrNull(get("ap")) ?? 0;
1046
+ const length = Math.hypot(run[0], run[1]);
1047
+ if (ap !== 0 || length === 0 || bezierControls(get, run) === null) {
1048
+ return;
1049
+ }
1050
+ const [ux, uy] = [run[0] / length, run[1] / length];
1051
+ const r = 1 / Math.hypot(ux / (target[0] / 2), uy / (target[1] / 2));
1052
+ const back = 1.5 + 5 * (numberOrNull(get("s")) ?? 1);
1053
+ const turn = -(numberOrNull(get("a2")) ?? 0) * Math.PI / 180;
1054
+ const [c, s] = [Math.cos(turn), Math.sin(turn)];
1055
+ const end = [run[0] - r * ux - back * (ux * c - uy * s), run[1] - r * uy - back * (ux * s + uy * c)];
1056
+ const controls = bezierControls(get, end);
1057
+ if (controls === null) {
1058
+ return;
1059
+ }
1060
+ const L2 = length * length;
1061
+ const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
1062
+ const bends = controls.map(([along, left]) => {
1063
+ const [x, y] = [along * end[0] + left * end[1], along * end[1] - left * end[0]];
1064
+ return `${fraction((x * run[0] + y * run[1]) / L2)},${fraction((x * run[1] - y * run[0]) / L2)}`;
1065
+ });
1066
+ put("bends", bends.join(" "));
1067
+ }
1068
+ function bezierControls(get, run) {
1069
+ const [a1, k1, a2, k2] = ["a1", "k1", "a2", "k2"].map((key) => numberOrNull(get(key)));
1070
+ if (a1 === null && k1 === null && a2 === null && k2 === null || run === null || run[0] === 0 && run[1] === 0) {
1071
+ return null;
1072
+ }
1073
+ const [s, t] = [k1 ?? 1, k2 ?? 1];
1074
+ if (s < 0 || t < 0) {
1075
+ return null;
1076
+ }
1077
+ const rad = Math.PI / 180;
1078
+ const [u, v] = [(a1 ?? 0) * rad, (a2 ?? 0) * rad];
1079
+ return [
1080
+ [s / 2 * Math.cos(u), -s / 2 * Math.sin(u)],
1081
+ [1 - t / 2 * Math.cos(v), -t / 2 * Math.sin(v)]
1082
+ ];
1083
+ }
1084
+ function lineDirection(get, run, along) {
1085
+ const controls = bezierControls(get, run);
1086
+ let [dx, dy] = run;
1087
+ if (controls !== null) {
1088
+ const t = Math.min(1, Math.max(0, along));
1089
+ const p = [[0, 0], ...controls, [1, 0]];
1090
+ 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]);
1091
+ const [a, l] = [d(0), d(1)];
1092
+ [dx, dy] = [a * run[0] + l * run[1], a * run[1] - l * run[0]];
1093
+ }
1094
+ return Math.atan2(dy, dx) * 180 / Math.PI;
1095
+ }
1096
+ function readLineValue(value, get, put, directed = true) {
1097
+ if (value === 0) {
1098
+ put("visible", false);
1099
+ } else if (value !== null && value < 0 && get("p") === null) {
1100
+ put("lineStyle", pajekDash(get, directed));
1101
+ }
1102
+ }
1103
+ const PAJEK_DASH = 5;
1104
+ function pajekDash(get, directed) {
1105
+ const w = numberOrNull(get("w"));
1106
+ const width = (w ?? 1) * (directed ? 1 : EDGE_WIDTH_PER_W);
1107
+ return PAJEK_DASH <= 1.5 * Math.max(1, width) ? "dotted" : "dashed";
1108
+ }
1109
+ function readHooks(get, put, source, target) {
1110
+ for (const [key, property, shape] of [
1111
+ ["h1", "sourcePort", source],
1112
+ ["h2", "targetPort", target]
1113
+ ]) {
1114
+ const hook = numberOrNull(get(key));
1115
+ const port = hook === null ? null : hookPort(shape, hook);
1116
+ if (port !== null) {
1117
+ const round = (v) => String(Number(v.toFixed(4)) + 0);
1118
+ put(property, `${round(port[0])},${round(port[1])}`);
1119
+ }
1120
+ }
1121
+ }
1122
+ function hookPort(shape, hook) {
1123
+ if (!Number.isInteger(hook) || hook < 1) {
1124
+ return null;
1125
+ }
1126
+ const keyword = typeof shape === "string" ? shape.toLowerCase() : "ellipse";
1127
+ if (keyword === "ellipse" || keyword === "cross") {
1128
+ const a = hook * Math.PI / 180;
1129
+ return [Math.cos(a), Math.sin(a)];
1130
+ }
1131
+ if (keyword !== "box" || hook > 400) {
1132
+ return null;
1133
+ }
1134
+ const d = hook * 0.02;
1135
+ if (hook <= 50) {
1136
+ return [1, d];
1137
+ }
1138
+ if (hook <= 150) {
1139
+ return [2 - d, 1];
1140
+ }
1141
+ if (hook <= 250) {
1142
+ return [-1, 4 - d];
1143
+ }
1144
+ return hook <= 350 ? [d - 6, -1] : [1, d - 8];
1145
+ }
1146
+ function numberOrNull(raw) {
1147
+ if (typeof raw === "string" && raw.trim() !== "") {
1148
+ raw = Number(raw);
1149
+ }
1150
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
1151
+ }
1152
+ function readArrowPosition(raw, put, at) {
1153
+ if (raw === null) {
1154
+ return;
1155
+ }
1156
+ const ap = canonNumber(raw, at("arrowPosition"));
1157
+ if (ap !== null && ap > 1) {
1158
+ noteAt(at("arrowPosition"), STYLE_ISSUE.NOT_CARRIED, `ap ${String(ap)}`);
1159
+ return;
1160
+ }
1161
+ if (ap !== 0) {
1162
+ put("arrowPosition", ap);
414
1163
  }
415
1164
  }
416
1165
  function cells(table, i) {
417
- return (key) => table.has(key) ? plainCell(table.value(key, i)) : null;
1166
+ return (key) => {
1167
+ const v = table.has(key) ? plainCell(table.value(key, i)) : null;
1168
+ return COLOR_PARAMS.has(key) && typeof v === "string" && NUMERIC_COLOR.test(v) ? null : v;
1169
+ };
418
1170
  }
1171
+ const COLOR_PARAMS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
1172
+ const NUMERIC_COLOR = /^[\d.]+(?: [\d.]+)*$/;
419
1173
  function directedEdges(snapshot) {
420
1174
  const out = new Array(snapshot.edgeCount).fill(snapshot.directed);
421
1175
  const col = snapshot.directed ? snapshot.edges.byRole("directed") : null;
@@ -431,32 +1185,72 @@ function styleColumns(table, keys) {
431
1185
  }
432
1186
  function pajekStyles(snapshot, context) {
433
1187
  const notes = new StyleNotes();
1188
+ const { block, draw, voided } = keptOf(context.kept);
1189
+ const labels = drawsLineLabels(draw);
1190
+ const place = places(snapshot);
1191
+ const window = draw ?? { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
1192
+ const loops = /* @__PURE__ */ new Map();
1193
+ const runOf = (e) => {
1194
+ const [s, t] = [place(snapshot.edgeSource(e)), place(snapshot.edgeTarget(e))];
1195
+ return s === null || t === null ? null : [(t[0] - s[0]) * window.width, (t[1] - s[1]) * window.height];
1196
+ };
434
1197
  const read = (target) => {
435
1198
  const table = target === "node" ? snapshot.nodes : snapshot.edges;
436
1199
  const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
437
1200
  const out = valueColumns(n);
1201
+ const carry = carriedParams(target === "node" ? CARRIED.node : CARRIED_LINE, target === "node");
438
1202
  for (let i = 0; i < n; i++) {
439
1203
  context.budget.spend(target, 1);
440
1204
  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
- );
1205
+ const put = (property, value) => {
1206
+ out.put(i, property, value);
1207
+ };
1208
+ const own = cells(table, i);
1209
+ const get = target === "node" && voided.has(i) ? voidedParams(own, keywords[i - 1] ?? null) : carry(own);
1210
+ if (target === "node") {
1211
+ readVertex(get, put, at, place(i));
1212
+ keywords[i] = get(SHAPE_COLUMN);
1213
+ } else {
1214
+ readEdge(i, get, put, at);
1215
+ }
448
1216
  }
449
1217
  return out.values;
450
1218
  };
1219
+ const readEdge = (i, get, put, at) => {
1220
+ const run = runOf(i);
1221
+ const loop = run !== null && block === null && snapshot.edgeSource(i) === snapshot.edgeTarget(i) ? (controls) => {
1222
+ loops.set(i, controls);
1223
+ } : null;
1224
+ readLine(get, put, at, directed[i], labels, run, loop);
1225
+ if (directed[i] && loop === null && run !== null) {
1226
+ readArcEnd(get, put, run, targetSize(snapshot.edgeTarget(i)));
1227
+ }
1228
+ readLineValue(lineValue(i), get, put, directed[i]);
1229
+ readHooks(get, put, keywords[snapshot.edgeSource(i)], keywords[snapshot.edgeTarget(i)]);
1230
+ };
1231
+ const directed = directedEdges(snapshot);
1232
+ const keywords = [];
1233
+ const weights = explicitWeights(snapshot);
1234
+ const lineValue = (e) => weights.isExplicit(e) ? weights.value(e) : numberOrNull(cells(snapshot.edges, e)(VALUE_COLUMN));
451
1235
  const node = read("node");
1236
+ const targetSize = (v) => {
1237
+ const size = (property) => {
1238
+ const s = node[property]?.[v];
1239
+ return typeof s === "number" && s > 0 ? s : PAJEK_VERTEX_SIZE;
1240
+ };
1241
+ return [size("width"), size("height")];
1242
+ };
452
1243
  const edge = read("edge");
453
- const block = typeof context.kept === "string" ? context.kept : null;
1244
+ if (draw !== null) {
1245
+ drawVertices(draw, snapshot, node);
1246
+ drawLines(draw, snapshot, node, edge);
1247
+ }
1248
+ layLoops(snapshot, loops, node, edge);
454
1249
  if (block !== null) {
455
- exactFromBlock(snapshot, block, { node, edge });
1250
+ exactFromBlock(snapshot, block, { node, edge }, labels);
456
1251
  }
457
1252
  const rules = [];
458
1253
  const columns = /* @__PURE__ */ new Map();
459
- const directed = directedEdges(snapshot);
460
1254
  if (directed.some(Boolean)) {
461
1255
  columns.set(
462
1256
  DIRECTED_KEY,
@@ -468,14 +1262,14 @@ function pajekStyles(snapshot, context) {
468
1262
  role: "group",
469
1263
  origin: "tool",
470
1264
  where: { has: { style: DIRECTED_KEY } },
471
- set: { targetArrow: "triangle" }
1265
+ set: { targetArrow: "triangle", color: ARC_DEFAULTS.color, width: ARC_DEFAULTS.width }
472
1266
  });
473
1267
  }
474
1268
  return {
475
1269
  canonical: true,
476
1270
  dialect: "dvips",
477
1271
  tool: "pajek",
478
- units: "relative",
1272
+ units: "px",
479
1273
  node: { values: node },
480
1274
  edge: { values: edge, rules, columns },
481
1275
  notes: notes.list(),
@@ -486,6 +1280,39 @@ function pajekStyles(snapshot, context) {
486
1280
  }
487
1281
  };
488
1282
  }
1283
+ function places(snapshot) {
1284
+ const col = snapshot.nodes.byRole("position");
1285
+ return (i) => {
1286
+ const v = col === null || col === void 0 ? null : col.value(i);
1287
+ if (v === null || typeof v !== "object" || !("length" in v)) {
1288
+ return null;
1289
+ }
1290
+ const [x, y] = v;
1291
+ return typeof x === "number" && typeof y === "number" ? [x, y] : null;
1292
+ };
1293
+ }
1294
+ function keptOf(kept) {
1295
+ if (typeof kept === "string") {
1296
+ return { block: kept, draw: null, voided: /* @__PURE__ */ new Set() };
1297
+ }
1298
+ if (typeof kept === "object" && kept !== null) {
1299
+ const { block, pajekDraw, voided } = kept;
1300
+ return {
1301
+ block: typeof block === "string" ? block : null,
1302
+ draw: pajekDraw ?? null,
1303
+ voided: new Set(voided ?? [])
1304
+ };
1305
+ }
1306
+ return { block: null, draw: null, voided: /* @__PURE__ */ new Set() };
1307
+ }
1308
+ function voidedParams(own, before) {
1309
+ return (key) => {
1310
+ if (key === LABEL_COLUMN) {
1311
+ return own(key);
1312
+ }
1313
+ return key === SHAPE_COLUMN ? before : null;
1314
+ };
1315
+ }
489
1316
  const SHAPES = /* @__PURE__ */ new Map([
490
1317
  ["ellipse", "ellipse"],
491
1318
  ["rectangle", "box"],
@@ -526,9 +1353,37 @@ function shapeKeyword(get, approximate) {
526
1353
  if (keyword !== void 0) {
527
1354
  return keyword;
528
1355
  }
1356
+ if (shape === "polygon" && diamondQ(get) !== null) {
1357
+ return "diamond";
1358
+ }
529
1359
  approximate("shape", shape);
1360
+ const points = get("shapePoints");
1361
+ if (shape === "polygon" && points !== null) {
1362
+ approximate("shapePoints", points);
1363
+ }
530
1364
  return NEAREST_SHAPES.get(shape) ?? "ellipse";
531
1365
  }
1366
+ function diamondQ(get) {
1367
+ const points = get("shapePoints");
1368
+ const corners = typeof points === "string" ? points.trim().split(/\s+/).map((p) => p.split(",").map(Number)) : [];
1369
+ if (corners.length !== 6) {
1370
+ return null;
1371
+ }
1372
+ const q = corners[2][0];
1373
+ const want = [
1374
+ [-1, 0],
1375
+ [-q, 1],
1376
+ [q, 1],
1377
+ [1, 0],
1378
+ [q, -1],
1379
+ [-q, -1]
1380
+ ];
1381
+ return want.every(([x, y], k) => corners[k][0] === x && corners[k][1] === y) ? q : null;
1382
+ }
1383
+ function pajekDefault(target, property) {
1384
+ const values = toolDefaults("pajek")?.[target];
1385
+ return values?.[property]?.value;
1386
+ }
532
1387
  function vertexParams(get, approximate) {
533
1388
  const out = /* @__PURE__ */ new Map();
534
1389
  opaque(get, ["fillOpacity", "opacity"], approximate);
@@ -536,54 +1391,117 @@ function vertexParams(get, approximate) {
536
1391
  if (keyword !== "ellipse") {
537
1392
  out.set(SHAPE_COLUMN, keyword);
538
1393
  }
1394
+ const q = diamondQ(get);
1395
+ if (q !== null && q !== PAJEK_DIAMOND_Q) {
1396
+ out.set("q", q);
1397
+ }
1398
+ vertexColorParams(get, out);
1399
+ vertexSizeParams(get, out);
1400
+ const bw = get("borderWidth");
1401
+ if (typeof bw === "number" && bw !== pajekDefault("node", "borderWidth")) {
1402
+ out.set("bw", bw);
1403
+ }
1404
+ fontParam(get, out, pajekDefault("node", "labelFont"));
1405
+ labelPositionParams(get, out, approximate);
1406
+ return out;
1407
+ }
1408
+ function vertexColorParams(get, out) {
539
1409
  const colors = [
540
1410
  ["fill", "ic"],
541
1411
  ["borderColor", "bc"],
542
1412
  ["labelColor", "lc"]
543
1413
  ];
544
- const numbers = [
545
- ["width", "x_fact"],
546
- ["height", "y_fact"],
547
- ["labelSize", "fos"]
548
- ];
549
1414
  for (const [property, key] of colors) {
550
1415
  const v = get(property);
551
- if (typeof v === "string" && (property === "fill" || v !== "#000000")) {
1416
+ if (typeof v === "string" && v !== pajekDefault("node", property)) {
552
1417
  out.set(key, pajekColorText(v));
553
1418
  }
554
1419
  }
555
- for (const [property, key] of numbers) {
1420
+ }
1421
+ function vertexSizeParams(get, out) {
1422
+ const numbers = [
1423
+ ["width", "x_fact", PAJEK_VERTEX_SIZE],
1424
+ ["height", "y_fact", PAJEK_VERTEX_SIZE],
1425
+ ["labelSize", "fos", 1]
1426
+ ];
1427
+ const figure = PAJEK_FIGURES.get(String(get("shape")));
1428
+ for (const [property, key, per] of numbers) {
556
1429
  const v = get(property);
557
- if (typeof v === "number") {
558
- out.set(key, v);
1430
+ let over = 1;
1431
+ if (figure !== void 0 && key !== "fos") {
1432
+ over = figure[key === "x_fact" ? 0 : 1];
1433
+ }
1434
+ if (typeof v === "number" && (over !== 1 || v !== pajekDefault("node", property))) {
1435
+ out.set(key, Number((v / (per * over)).toPrecision(15)));
559
1436
  }
560
1437
  }
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);
1438
+ }
1439
+ function fontParam(get, out, skip) {
1440
+ const font = get("labelFont");
1441
+ const name = typeof font === "string" && font !== "" ? graphvizFontName(font, false, false) : null;
1442
+ if (name !== null && name !== skip) {
1443
+ out.set("font", name);
1444
+ }
1445
+ }
1446
+ function labelPositionParams(get, out, approximate) {
1447
+ const position = get("labelPosition");
1448
+ if (typeof position !== "string") {
1449
+ return;
1450
+ }
1451
+ if (position === "center") {
1452
+ const polar = polarOf(get);
1453
+ if (polar === null) {
1454
+ out.set("lr", 0);
1455
+ } else if (polar[0] !== PAJEK_LABEL_RADIUS || polar[1] !== PAJEK_LABEL_ANGLE) {
1456
+ out.set("lr", polar[0]);
1457
+ out.set("lphi", polar[1]);
568
1458
  }
1459
+ return;
1460
+ }
1461
+ const nearest = NEAREST_SIDES.get(position);
1462
+ if (nearest !== void 0) {
1463
+ approximate("labelPosition", position);
1464
+ }
1465
+ const angle = SIDE_ANGLES.get(nearest ?? position);
1466
+ if (angle !== void 0 && angle !== PAJEK_LABEL_ANGLE) {
1467
+ out.set("lphi", angle);
569
1468
  }
570
- return out;
1469
+ }
1470
+ function polarOf(get) {
1471
+ const [x, y, shift] = [get("labelOffsetX"), get("labelOffsetY"), get("labelShiftX")];
1472
+ if (typeof x !== "number" || typeof y !== "number" || shift !== 0.5) {
1473
+ return null;
1474
+ }
1475
+ const size = get("labelSize");
1476
+ const up = y + PAJEK_BASELINE_TO_MIDDLE * (typeof size === "number" ? size : PAJEK_LABEL_SIZE);
1477
+ const round = (v) => Number(v.toFixed(6)) + 0;
1478
+ const lr = round(Math.hypot(x, up));
1479
+ return lr === 0 ? null : [lr, round((Math.atan2(-up, x) * 180 / Math.PI % 360 + 360) % 360)];
1480
+ }
1481
+ function lineDefaults(directed) {
1482
+ return directed ? ARC_DEFAULTS : { color: pajekDefault("edge", "color"), width: pajekDefault("edge", "width") };
571
1483
  }
572
1484
  function lineParams(get, directed, approximate) {
573
1485
  const out = /* @__PURE__ */ new Map();
574
1486
  opaque(get, ["opacity"], approximate);
1487
+ const defaults = lineDefaults(directed);
575
1488
  const color = get("color");
576
- if (typeof color === "string" && color !== "#000000") {
1489
+ if (typeof color === "string" && color !== defaults.color) {
577
1490
  out.set("c", pajekColorText(color));
578
1491
  }
579
1492
  const width = get("width");
580
- if (typeof width === "number") {
581
- out.set("w", width);
1493
+ if (typeof width === "number" && width !== defaults.width) {
1494
+ out.set("w", directed ? width : Number((width / EDGE_WIDTH_PER_W).toPrecision(15)));
582
1495
  }
583
1496
  const lineStyle = get("lineStyle");
584
- if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, approximate)) {
1497
+ if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, out, directed, approximate)) {
585
1498
  out.set("p", "Dots");
586
1499
  }
1500
+ const position = get("arrowPosition");
1501
+ if (typeof position === "number" && position > 0) {
1502
+ out.set("ap", position);
1503
+ }
1504
+ lineLabelParams(get, out, approximate);
587
1505
  const target = get("targetArrow");
588
1506
  if (target !== null && target !== (directed ? "triangle" : "none")) {
589
1507
  approximate("targetArrow", target);
@@ -594,47 +1512,50 @@ function lineParams(get, directed, approximate) {
594
1512
  }
595
1513
  return out;
596
1514
  }
597
- function pajekDots(lineStyle, approximate) {
598
- if (lineStyle === "dotted") {
599
- return true;
1515
+ function lineLabelParams(get, out, approximate) {
1516
+ const label = get("label");
1517
+ if (typeof label === "string" && label !== "") {
1518
+ const text = pajekLabelText(label);
1519
+ if (text !== label) {
1520
+ approximate("label", label);
1521
+ }
1522
+ out.set("l", text);
600
1523
  }
601
- approximate("lineStyle", lineStyle);
602
- return lineStyle === "dashed" || lineStyle === "dash-dot" || lineStyle === "long-dash";
603
- }
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));
1524
+ const labelColor = get("labelColor");
1525
+ if (typeof labelColor === "string") {
1526
+ out.set("lc", pajekColorText(labelColor));
1527
+ }
1528
+ const labelSize = get("labelSize");
1529
+ if (typeof labelSize === "number") {
1530
+ out.set("fos", labelSize);
608
1531
  }
609
- return (i) => (property) => columns.get(property)?.[i] ?? null;
1532
+ fontParam(get, out);
610
1533
  }
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;
1534
+ function pajekDots(lineStyle, params, directed, approximate) {
1535
+ if (lineStyle === pajekDash((key) => params.get(key) ?? null, directed)) {
1536
+ return true;
616
1537
  }
1538
+ approximate("lineStyle", lineStyle);
1539
+ return ["dashed", "dotted", "dash-dot", "long-dash"].includes(lineStyle);
1540
+ }
1541
+ function exactFromBlock(snapshot, text, read, labels) {
617
1542
  const notes = new StyleNotes();
618
1543
  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
- }
1544
+ takeFromBlock(snapshot, text, "pajek", (target) => ({
1545
+ values: read[target],
1546
+ properties: READ[target],
1547
+ writes: PAJEK_STYLE_CAPABILITIES[target],
1548
+ readBack: (i, want) => {
1549
+ const back = writtenAndReadBack(target, want, directed[i], notes, labels);
1550
+ return (property) => back.get(property) ?? null;
1551
+ },
1552
+ // a label the block places by a side clears the offsets its `lphi` reads back as
1553
+ take: (property, wanted) => wanted !== null || LABEL_PLACE.has(property) || OUTLINE.has(property)
1554
+ }));
636
1555
  }
637
- function writtenAndReadBack(target, want, directed, notes) {
1556
+ const OUTLINE = /* @__PURE__ */ new Set(["shapePoints", "shapePointsStretch"]);
1557
+ const LABEL_PLACE = /* @__PURE__ */ new Set(["labelOffsetX", "labelOffsetY", "labelShiftX"]);
1558
+ function writtenAndReadBack(target, want, directed, notes, labels) {
638
1559
  const ignore = () => void 0;
639
1560
  const params = target === "node" ? vertexParams(want, ignore) : lineParams(want, directed, ignore);
640
1561
  const back = /* @__PURE__ */ new Map();
@@ -642,15 +1563,26 @@ function writtenAndReadBack(target, want, directed, notes) {
642
1563
  if (typeof label === "string") {
643
1564
  params.set(LABEL_COLUMN, pajekLabelText(label));
644
1565
  }
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
- );
1566
+ if (target === "node" && [...params.keys()].every((key) => key === LABEL_COLUMN)) {
1567
+ params.set(SHAPE_COLUMN, "ellipse");
1568
+ }
1569
+ for (const key of target === "edge" ? CARRIED.edge : []) {
1570
+ if (!params.has(key)) {
1571
+ params.set(key, lineRestated(key, directed));
1572
+ }
1573
+ }
1574
+ const get = (key) => params.get(key) ?? null;
1575
+ const put = (property, value) => {
1576
+ if (value !== null) {
1577
+ back.set(property, value);
1578
+ }
1579
+ };
1580
+ const at = (property) => ({ notes, target, property });
1581
+ if (target === "node") {
1582
+ readVertex(get, put, at);
1583
+ } else {
1584
+ readLine(get, put, at, directed, labels);
1585
+ }
654
1586
  return back;
655
1587
  }
656
1588
  function pajekStyledExport(snapshot, input) {
@@ -665,14 +1597,15 @@ function pajekStyledExport(snapshot, input) {
665
1597
  const approximate = (property, value) => {
666
1598
  approximated.add(target, property, value);
667
1599
  };
668
- const get = getter((t, p) => input.picture(t, p), target);
1600
+ const get = elementValues((t, p) => input.picture(t, p), target, PAJEK_STYLE_CAPABILITIES[target]);
669
1601
  const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
670
1602
  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
- );
1603
+ const columns = paramColumns(n, params);
1604
+ if (target === "edge") {
1605
+ keepLineLabels(snapshot, columns);
1606
+ }
1607
+ restateCarried(target, columns, directed);
1608
+ replaceParamColumns(table, target === "node" ? [SHAPE_COLUMN, ...NODE_KEYS] : EDGE_KEYS, columns);
676
1609
  }
677
1610
  out.nodes.set(
678
1611
  LABEL_COLUMN,
@@ -687,6 +1620,23 @@ function pajekStyledExport(snapshot, input) {
687
1620
  notes.push(...styleBlockLosses(block, input.rules.styles.rules.length, "size"));
688
1621
  return { snapshot: out, comment: PAJEK_STYLE_COMMENT + block, notes };
689
1622
  }
1623
+ function keepLineLabels(snapshot, columns) {
1624
+ if (!snapshot.edges.has("l")) {
1625
+ return;
1626
+ }
1627
+ const own = (e) => plainCell(snapshot.edges.value("l", e));
1628
+ let col = columns.get("l");
1629
+ for (let e = 0; e < snapshot.edgeCount; e++) {
1630
+ const v = own(e);
1631
+ if (typeof v === "string" && v !== "" && (col?.[e] ?? null) === null) {
1632
+ col ??= new Array(snapshot.edgeCount).fill(null);
1633
+ col[e] = pajekLabelText(v);
1634
+ }
1635
+ }
1636
+ if (col !== void 0) {
1637
+ columns.set("l", col);
1638
+ }
1639
+ }
690
1640
  function drawnLabels(input, n, approximated) {
691
1641
  const drawn = input.picture("node", "label");
692
1642
  const out = new Array(n).fill("");
@@ -715,6 +1665,45 @@ function replaceParamColumns(table, keys, columns) {
715
1665
  table.set(key, col, { dtype: numeric ? "f64" : "string" });
716
1666
  }
717
1667
  }
1668
+ function restateCarried(target, columns, directed) {
1669
+ if (target === "node") {
1670
+ const all = [...columns.values()];
1671
+ if (all.length === 0) {
1672
+ return;
1673
+ }
1674
+ const n = all[0].length;
1675
+ const shape = columns.get(SHAPE_COLUMN) ?? new Array(n).fill(null);
1676
+ for (let i = 0; i < n; i++) {
1677
+ if (all.every((col) => col[i] === null)) {
1678
+ shape[i] = "ellipse";
1679
+ }
1680
+ }
1681
+ columns.set(SHAPE_COLUMN, shape);
1682
+ return;
1683
+ }
1684
+ for (const key of CARRIED.edge) {
1685
+ const col = columns.get(key);
1686
+ if (col === void 0) {
1687
+ continue;
1688
+ }
1689
+ for (let i = 0; i < col.length; i++) {
1690
+ col[i] ??= lineRestated(key, directed[i]);
1691
+ }
1692
+ }
1693
+ }
1694
+ function lineRestated(key, directed) {
1695
+ const defaults = lineDefaults(directed);
1696
+ switch (key) {
1697
+ case "c":
1698
+ return pajekColorText(String(defaults.color));
1699
+ case "w":
1700
+ return directed ? Number(defaults.width) : Number(defaults.width) / EDGE_WIDTH_PER_W;
1701
+ case "p":
1702
+ return "Solid";
1703
+ default:
1704
+ return 0;
1705
+ }
1706
+ }
718
1707
  function paramColumns(n, params) {
719
1708
  const columns = /* @__PURE__ */ new Map();
720
1709
  for (let i = 0; i < n; i++) {
@@ -815,58 +1804,58 @@ const CAPABILITIES = capabilities({
815
1804
  });
816
1805
  function plan(table, domain, notes) {
817
1806
  const planned = [];
818
- for (const column of table) {
819
- const slot = columnSlot(column, domain, notes);
1807
+ for (const column2 of table) {
1808
+ const slot = columnSlot(column2, domain, notes);
820
1809
  if (slot !== null) {
821
- planned.push({ column, slot });
1810
+ planned.push({ column: column2, slot });
822
1811
  }
823
1812
  }
824
1813
  return planned;
825
1814
  }
826
- function columnNote(notes, code, message, column) {
827
- notes?.push(note(code, message, column.meta.name, column.length - column.nullCount));
1815
+ function columnNote(notes, code, message, column2) {
1816
+ notes?.push(note(code, message, column2.meta.name, column2.length - column2.nullCount));
828
1817
  }
829
- function columnSlot(column, domain, notes) {
830
- const { role, name } = column.meta;
1818
+ function columnSlot(column2, domain, notes) {
1819
+ const { role, name } = column2.meta;
831
1820
  if (role === "label" && domain === "node") {
832
- return labelSlot(column, notes);
1821
+ return labelSlot(column2, notes);
833
1822
  }
834
1823
  if (role === "position") {
835
- return positionSlot(column, domain, notes);
1824
+ return positionSlot(column2, domain, notes);
836
1825
  }
837
1826
  if (role === "spells") {
838
- return spellsSlot(column, domain, notes);
1827
+ return spellsSlot(column2, domain, notes);
839
1828
  }
840
1829
  if (role !== null && DROPPED_TEMPORAL_ROLES.has(role)) {
841
1830
  columnNote(
842
1831
  notes,
843
1832
  PAJEK_LOSS.TEMPORAL_DROPPED,
844
1833
  `${domain} column "${name}" (${role}) cannot be written; Pajek intervals come from the spells role`,
845
- column
1834
+ column2
846
1835
  );
847
1836
  return null;
848
1837
  }
849
- if (writtenElsewhere(column, domain)) {
1838
+ if (writtenElsewhere(column2, domain)) {
850
1839
  return null;
851
1840
  }
852
- return namedSlot(column, domain, notes);
1841
+ return namedSlot(column2, domain, notes);
853
1842
  }
854
- function labelSlot(column, notes) {
855
- const { name, dtype } = column.meta;
1843
+ function labelSlot(column2, notes) {
1844
+ const { name, dtype } = column2.meta;
856
1845
  if (dtype !== "string" && dtype !== "dict") {
857
1846
  columnNote(
858
1847
  notes,
859
1848
  PAJEK_LOSS.LABEL_AS_TEXT,
860
1849
  `node column "${name}" (label) is ${dtype}; labels are text and re-import as string`,
861
- column
1850
+ column2
862
1851
  );
863
1852
  }
864
1853
  return "label";
865
1854
  }
866
- function positionSlot(column, domain, notes) {
867
- const { name, components } = column.meta;
1855
+ function positionSlot(column2, domain, notes) {
1856
+ const { name, components } = column2.meta;
868
1857
  if (domain === "edge") {
869
- columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column);
1858
+ columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column2);
870
1859
  return null;
871
1860
  }
872
1861
  if (components === 2 || components === 3) {
@@ -876,12 +1865,12 @@ function positionSlot(column, domain, notes) {
876
1865
  notes,
877
1866
  PAJEK_LOSS.POSITION_STRIDE,
878
1867
  `node column "${name}" (position) has ${components} components; Pajek coordinates are x y [z]`,
879
- column
1868
+ column2
880
1869
  );
881
1870
  return null;
882
1871
  }
883
- function spellsSlot(column, domain, notes) {
884
- const { name, dtype, itemDtype } = column.meta;
1872
+ function spellsSlot(column2, domain, notes) {
1873
+ const { name, dtype, itemDtype } = column2.meta;
885
1874
  if (dtype === "list" && (itemDtype === "f64" || itemDtype === "i32" || itemDtype === "f32")) {
886
1875
  return "spells";
887
1876
  }
@@ -889,22 +1878,22 @@ function spellsSlot(column, domain, notes) {
889
1878
  notes,
890
1879
  LOSS.SPELLS,
891
1880
  `${domain} column "${name}" (spells) is not a list of number pairs; it cannot be written`,
892
- column
1881
+ column2
893
1882
  );
894
1883
  return null;
895
1884
  }
896
- function writtenElsewhere(column, domain) {
897
- const { role, dtype } = column.meta;
1885
+ function writtenElsewhere(column2, domain) {
1886
+ const { role, dtype } = column2.meta;
898
1887
  if (role !== null && (STRUCTURAL_ROLES.has(role) || CHECKED_ROLES.has(role))) {
899
1888
  return true;
900
1889
  }
901
1890
  return domain === "edge" && role === "id" || dtype === "list" || dtype === "json";
902
1891
  }
903
- function namedSlot(column, domain, notes) {
904
- const { name, dtype } = column.meta;
1892
+ function namedSlot(column2, domain, notes) {
1893
+ const { name, dtype } = column2.meta;
905
1894
  const text = dtype === "dict" || dtype === "string";
906
1895
  if (text && domain === "node" && name === SHAPE_COLUMN) {
907
- return shapeSlot(column, notes);
1896
+ return shapeSlot(column2, notes);
908
1897
  }
909
1898
  if (text && domain === "edge" && name === RELATION_COLUMN) {
910
1899
  return "relation";
@@ -914,22 +1903,22 @@ function namedSlot(column, domain, notes) {
914
1903
  notes,
915
1904
  PAJEK_LOSS.KEY_DROPPED,
916
1905
  `${domain} column "${name}" cannot be a Pajek parameter key; it is not written`,
917
- column
1906
+ column2
918
1907
  );
919
1908
  return null;
920
1909
  }
921
1910
  return "param";
922
1911
  }
923
- function shapeSlot(column, notes) {
924
- if (allShapeKeywords(column)) {
1912
+ function shapeSlot(column2, notes) {
1913
+ if (allShapeKeywords(column2)) {
925
1914
  return "shape";
926
1915
  }
927
- if (column.meta.dtype === "dict") {
1916
+ if (column2.meta.dtype === "dict") {
928
1917
  columnNote(
929
1918
  notes,
930
1919
  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
1920
+ `node column "${column2.meta.name}" holds values outside the Pajek shape keywords; it is written as a parameter and reads back as string`,
1921
+ column2
933
1922
  );
934
1923
  }
935
1924
  return "param";
@@ -937,9 +1926,9 @@ function shapeSlot(column, notes) {
937
1926
  function labelNotes(snapshot, nodePlan, notes) {
938
1927
  let labels = null;
939
1928
  let carried = 0;
940
- for (const { column, slot } of nodePlan) {
1929
+ for (const { column: column2, slot } of nodePlan) {
941
1930
  if (slot === "label") {
942
- labels = column;
1931
+ labels = column2;
943
1932
  } else if (slot !== "skip" && slot !== "relation") {
944
1933
  carried++;
945
1934
  }
@@ -986,16 +1975,16 @@ function unlabeled(nodeCount, labels) {
986
1975
  }
987
1976
  return count;
988
1977
  }
989
- function allShapeKeywords(column) {
990
- for (let r = 0; r < column.length; r++) {
991
- if (column.isSet(r) && !SHAPES$1.has(column.value(r))) {
1978
+ function allShapeKeywords(column2) {
1979
+ for (let r = 0; r < column2.length; r++) {
1980
+ if (column2.isSet(r) && !SHAPES$1.has(column2.value(r))) {
992
1981
  return false;
993
1982
  }
994
1983
  }
995
1984
  return true;
996
1985
  }
997
- function note(code, message, column = null, count = null) {
998
- return Object.freeze({ code, message, column, count });
1986
+ function note(code, message, column2 = null, count = null) {
1987
+ return Object.freeze({ code, message, column: column2, count });
999
1988
  }
1000
1989
  function numberText(value, dtype) {
1001
1990
  switch (dtype) {
@@ -1013,53 +2002,53 @@ function numberText(value, dtype) {
1013
2002
  }
1014
2003
  }
1015
2004
  }
1016
- function cellText(column, row) {
1017
- switch (column.dtype) {
2005
+ function cellText(column2, row) {
2006
+ switch (column2.dtype) {
1018
2007
  case "f32":
1019
2008
  case "f64":
1020
2009
  case "i32":
1021
2010
  case "u32":
1022
2011
  case "u8": {
1023
- const value = column.value(row);
2012
+ const value = column2.value(row);
1024
2013
  if (typeof value === "number") {
1025
- return numberText(value, column.dtype);
2014
+ return numberText(value, column2.dtype);
1026
2015
  }
1027
2016
  const parts = [];
1028
2017
  const vector = value;
1029
2018
  for (let k = 0; k < vector.length; k++) {
1030
- parts.push(numberText(vector[k], column.dtype));
2019
+ parts.push(numberText(vector[k], column2.dtype));
1031
2020
  }
1032
2021
  return parts.join(" ");
1033
2022
  }
1034
2023
  case "bool":
1035
- return column.value(row) === true ? "true" : "false";
2024
+ return column2.value(row) === true ? "true" : "false";
1036
2025
  case "dict":
1037
2026
  case "string":
1038
- return column.value(row);
2027
+ return column2.value(row);
1039
2028
  case "list":
1040
2029
  case "json":
1041
- return JSON.stringify(column.value(row));
2030
+ return JSON.stringify(column2.value(row));
1042
2031
  default: {
1043
- const name = column.dtype;
2032
+ const name = column2.dtype;
1044
2033
  throw new Error(`unknown dtype ${name}`);
1045
2034
  }
1046
2035
  }
1047
2036
  }
1048
2037
  function checkCells(planned, domain, notes) {
1049
- for (const { column, slot } of planned) {
2038
+ for (const { column: column2, slot } of planned) {
1050
2039
  if (slot === "position" || slot === "spells") {
1051
2040
  continue;
1052
2041
  }
1053
- const { name } = column.meta;
2042
+ const { name } = column2.meta;
1054
2043
  let badText = 0;
1055
2044
  let nonFinite = 0;
1056
2045
  let typed = 0;
1057
- for (let r = 0; r < column.length; r++) {
1058
- if (!column.isSet(r)) {
2046
+ for (let r = 0; r < column2.length; r++) {
2047
+ if (!column2.isSet(r)) {
1059
2048
  continue;
1060
2049
  }
1061
- if (column.dtype === "f64" || column.dtype === "f32") {
1062
- const value = column.value(r);
2050
+ if (column2.dtype === "f64" || column2.dtype === "f32") {
2051
+ const value = column2.value(r);
1063
2052
  if (typeof value === "number") {
1064
2053
  if (!Number.isFinite(value)) {
1065
2054
  nonFinite++;
@@ -1067,8 +2056,8 @@ function checkCells(planned, domain, notes) {
1067
2056
  } else if (value !== void 0 && !Array.from(value).every((v) => Number.isFinite(v))) {
1068
2057
  nonFinite++;
1069
2058
  }
1070
- } else if (column.dtype === "string" || column.dtype === "dict") {
1071
- const text = column.value(r);
2059
+ } else if (column2.dtype === "string" || column2.dtype === "dict") {
2060
+ const text = column2.value(r);
1072
2061
  if (!isPajekLabel(text)) {
1073
2062
  badText++;
1074
2063
  } else if (slot === "param" && inferTextDtype(text) !== "string") {
@@ -1131,11 +2120,11 @@ function labelOf(labels, ids, i, needed) {
1131
2120
  }
1132
2121
  return null;
1133
2122
  }
1134
- function spellsText(column, row) {
1135
- if (column.dtype !== "list" || !column.isSet(row)) {
2123
+ function spellsText(column2, row) {
2124
+ if (column2.dtype !== "list" || !column2.isSet(row)) {
1136
2125
  return null;
1137
2126
  }
1138
- const items = column.sliceOf(row);
2127
+ const items = column2.sliceOf(row);
1139
2128
  if (items.length === 0) {
1140
2129
  return null;
1141
2130
  }
@@ -1146,29 +2135,29 @@ function spellsText(column, row) {
1146
2135
  }
1147
2136
  return formatIntervals(pairs);
1148
2137
  }
1149
- function coordinatesText(column, i, writeZ) {
1150
- if (!column.isSet(i)) {
2138
+ function coordinatesText(column2, i, writeZ) {
2139
+ if (!column2.isSet(i)) {
1151
2140
  return null;
1152
2141
  }
1153
- const dtype = column.dtype;
1154
- const vector = column.value(i);
2142
+ const dtype = column2.dtype;
2143
+ const vector = column2.value(i);
1155
2144
  const x = formatNumber(vector[0], dtype);
1156
2145
  const y = formatNumber(vector[1], dtype);
1157
- if (column.meta.components === 3 && writeZ) {
2146
+ if (column2.meta.components === 3 && writeZ) {
1158
2147
  return `${x} ${y} ${formatNumber(vector[2], dtype)}`;
1159
2148
  }
1160
2149
  return `${x} ${y}`;
1161
2150
  }
1162
- function needsZ(column) {
1163
- if (column.meta.components !== 3) {
2151
+ function needsZ(column2) {
2152
+ if (column2.meta.components !== 3) {
1164
2153
  return false;
1165
2154
  }
1166
- if (column.meta.extra.sourceDims !== 2) {
2155
+ if (column2.meta.extra.sourceDims !== 2) {
1167
2156
  return true;
1168
2157
  }
1169
- for (let i = 0; i < column.length; i++) {
1170
- if (column.isSet(i)) {
1171
- const vector = column.value(i);
2158
+ for (let i = 0; i < column2.length; i++) {
2159
+ if (column2.isSet(i)) {
2160
+ const vector = column2.value(i);
1172
2161
  if (vector[2] !== 0) {
1173
2162
  return true;
1174
2163
  }
@@ -1251,27 +2240,49 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
1251
2240
  }
1252
2241
  }
1253
2242
  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) {
2243
+ const slots = vertexSlots(nodePlan);
2244
+ const writeZ = slots.position !== null && needsZ(slots.position);
2245
+ for (let i = 0; i < snapshot.nodeCount; i++) {
2246
+ const parts = vertexParts(slots, i, writeZ);
2247
+ if (mangle && ids.isChanged(i)) {
2248
+ parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
2249
+ }
2250
+ if (slots.spells !== null) {
2251
+ const spells = spellsText(slots.spells, i);
2252
+ if (spells !== null) {
2253
+ parts.push(spells);
2254
+ }
2255
+ }
2256
+ const label = labelOf(slots.labels, ids, i, parts.length > 0);
2257
+ let line = String(i + 1);
2258
+ if (label !== null) {
2259
+ line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
2260
+ }
2261
+ if (parts.length > 0) {
2262
+ line += ` ${parts.join(" ")}`;
2263
+ }
2264
+ yield `${line}
2265
+ `;
2266
+ }
2267
+ }
2268
+ function vertexSlots(nodePlan) {
2269
+ const slots = { labels: null, position: null, shape: null, spells: null, params: [] };
2270
+ for (const { column: column2, slot } of nodePlan) {
1260
2271
  switch (slot) {
1261
2272
  case "label":
1262
- labels = column;
2273
+ slots.labels = column2;
1263
2274
  break;
1264
2275
  case "position":
1265
- position = column;
2276
+ slots.position = column2;
1266
2277
  break;
1267
2278
  case "shape":
1268
- shape = column;
2279
+ slots.shape = column2;
1269
2280
  break;
1270
2281
  case "spells":
1271
- nodeSpells = column;
2282
+ slots.spells = column2;
1272
2283
  break;
1273
2284
  case "param":
1274
- nodeParams.push(column);
2285
+ slots.params.push(column2);
1275
2286
  break;
1276
2287
  case "relation":
1277
2288
  case "skip":
@@ -1282,48 +2293,32 @@ function* writeVertices(snapshot, ids, nodePlan, mangle) {
1282
2293
  }
1283
2294
  }
1284
2295
  }
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))}`;
2296
+ return slots;
2297
+ }
2298
+ function vertexParts(slots, i, writeZ) {
2299
+ const { position, shape } = slots;
2300
+ const parts = [];
2301
+ const coordinates = position === null ? null : coordinatesText(position, i, writeZ);
2302
+ if (coordinates !== null) {
2303
+ parts.push(coordinates);
2304
+ }
2305
+ const placed = parts.length > 0;
2306
+ const shaped = shape?.isSet(i) === true;
2307
+ if (shaped) {
2308
+ const keyword = cellText(shape, i);
2309
+ parts.push(SHAPES$1.has(keyword) ? keyword : `${SHAPE_COLUMN} ${quotePajekLabel(keyword)}`);
2310
+ }
2311
+ const named = parts.length;
2312
+ for (const column2 of slots.params) {
2313
+ if (!column2.isSet(i)) {
2314
+ continue;
1320
2315
  }
1321
- if (parts.length > 0) {
1322
- line += ` ${parts.join(" ")}`;
2316
+ if (placed && !shaped && parts.length === named && VOIDING_KEYS.has(column2.meta.name)) {
2317
+ parts.push("ellipse");
1323
2318
  }
1324
- yield `${line}
1325
- `;
2319
+ parts.push(`${column2.meta.name} ${quotePajekLabel(cellText(column2, i))}`);
1326
2320
  }
2321
+ return parts;
1327
2322
  }
1328
2323
  function* writeLines(snapshot, edgePlan) {
1329
2324
  const folding = pairFolding(snapshot, { foldMutual: true });
@@ -1332,16 +2327,16 @@ function* writeLines(snapshot, edgePlan) {
1332
2327
  let relation = null;
1333
2328
  let edgeSpells = null;
1334
2329
  const edgeParams = [];
1335
- for (const { column, slot } of edgePlan) {
2330
+ for (const { column: column2, slot } of edgePlan) {
1336
2331
  switch (slot) {
1337
2332
  case "relation":
1338
- relation = column;
2333
+ relation = column2;
1339
2334
  break;
1340
2335
  case "spells":
1341
- edgeSpells = column;
2336
+ edgeSpells = column2;
1342
2337
  break;
1343
2338
  case "param":
1344
- edgeParams.push(column);
2339
+ edgeParams.push(column2);
1345
2340
  break;
1346
2341
  case "label":
1347
2342
  case "position":
@@ -1388,9 +2383,9 @@ function* writeLines(snapshot, edgePlan) {
1388
2383
  if (weight !== null) {
1389
2384
  line += ` ${weight}`;
1390
2385
  }
1391
- for (const column of edgeParams) {
1392
- if (column.isSet(e)) {
1393
- line += ` ${column.meta.name} ${quotePajekLabel(cellText(column, e))}`;
2386
+ for (const column2 of edgeParams) {
2387
+ if (column2.isSet(e)) {
2388
+ line += ` ${column2.meta.name} ${quotePajekLabel(cellText(column2, e))}`;
1394
2389
  }
1395
2390
  }
1396
2391
  if (edgeSpells !== null) {
@@ -1478,16 +2473,16 @@ function withOriginalIds(options) {
1478
2473
  }
1479
2474
  function ownedColumns(snapshot, planned) {
1480
2475
  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;
2476
+ const key = (column2) => `${column2.meta.domain}:${column2.meta.name}`;
2477
+ for (const { column: column2, slot } of planned) {
2478
+ const shapeParam = slot === "param" && column2.meta.domain === "node" && column2.meta.name === SHAPE_COLUMN;
1484
2479
  if (slot === "shape" || slot === "relation" || shapeParam) {
1485
- owned.add(key(column));
2480
+ owned.add(key(column2));
1486
2481
  }
1487
2482
  }
1488
- for (const column of [...snapshot.nodes, ...snapshot.edges]) {
1489
- if (column.meta.role === "spells") {
1490
- owned.add(key(column));
2483
+ for (const column2 of [...snapshot.nodes, ...snapshot.edges]) {
2484
+ if (column2.meta.role === "spells") {
2485
+ owned.add(key(column2));
1491
2486
  }
1492
2487
  }
1493
2488
  return owned;
@@ -1530,13 +2525,13 @@ function checkPlain(snapshot, options) {
1530
2525
  const owned = ownedColumns(snapshot, [...nodePlan, ...edgePlan]);
1531
2526
  notes.push(...capabilityNotes(snapshot, resolved, owned));
1532
2527
  labelNotes(snapshot, nodePlan, notes);
1533
- for (const column of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
2528
+ for (const column2 of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
1534
2529
  notes.push(
1535
2530
  note(
1536
2531
  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
2532
+ `edge column "${column2.meta.name}" (label) is written as a plain parameter; Pajek labels vertices only and the role is lost`,
2533
+ column2.meta.name,
2534
+ column2.length - column2.nullCount
1540
2535
  )
1541
2536
  );
1542
2537
  }
@@ -1731,7 +2726,7 @@ function spellsDecl() {
1731
2726
  origin: { format: "pajek", id: "interval" }
1732
2727
  };
1733
2728
  }
1734
- function positionDecl(sourceDims) {
2729
+ function positionDecl(sourceDims, window) {
1735
2730
  return {
1736
2731
  name: POSITION_COLUMN,
1737
2732
  dtype: "f64",
@@ -1740,10 +2735,21 @@ function positionDecl(sourceDims) {
1740
2735
  role: "position",
1741
2736
  origin: { format: "pajek", id: "coordinates" },
1742
2737
  // 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 }
2738
+ // centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position; one unit
2739
+ // is the Draw window's width in points across and its height down (500 each by default,
2740
+ // PAJEK_POINTS_PER_UNIT): Pajek stretches 0..1 to the window one axis at a time
2741
+ extra: {
2742
+ sourceDims,
2743
+ units: "file",
2744
+ pxPerUnit: window.width,
2745
+ ...window.height === window.width ? {} : { pxPerUnitY: window.height },
2746
+ yAxis: "down",
2747
+ zOrigin: 0.5,
2748
+ zeroUnplaced: true
2749
+ }
1745
2750
  };
1746
2751
  }
2752
+ const DEFAULT_WINDOW = { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
1747
2753
  class LineError extends Error {
1748
2754
  /**
1749
2755
  * Create a line error.
@@ -1770,8 +2776,11 @@ class PajekParser {
1770
2776
  * @param report - the report
1771
2777
  * @param options - the resolved common options
1772
2778
  * @param firstVertex - the firstVertex format option
2779
+ * @param window - the Draw window the coordinates are stretched to
1773
2780
  */
1774
- constructor(sink, report, options, firstVertex) {
2781
+ constructor(sink, report, options, firstVertex, window = DEFAULT_WINDOW) {
2782
+ this.keptBlock = null;
2783
+ this.voided = [];
1775
2784
  this.section = "none";
1776
2785
  this.kind = "directed";
1777
2786
  this.relation = null;
@@ -1808,6 +2817,7 @@ class PajekParser {
1808
2817
  this.ended = false;
1809
2818
  this.edgeParams = /* @__PURE__ */ new Map();
1810
2819
  this.styleBlockKept = false;
2820
+ this.window = window;
1811
2821
  this.sink = sink;
1812
2822
  this.report = report;
1813
2823
  this.options = options;
@@ -1827,7 +2837,8 @@ class PajekParser {
1827
2837
  const trimmed = text.trimStart();
1828
2838
  if (trimmed.startsWith(PAJEK_STYLE_COMMENT)) {
1829
2839
  this.styleBlockKept = true;
1830
- this.report.keepForStyles(trimmed.slice(PAJEK_STYLE_COMMENT.length));
2840
+ this.keptBlock = trimmed.slice(PAJEK_STYLE_COMMENT.length);
2841
+ this.report.keepForStyles(this.keptBlock);
1831
2842
  }
1832
2843
  }
1833
2844
  /**
@@ -2290,6 +3301,55 @@ class PajekParser {
2290
3301
  */
2291
3302
  vertexLine(text, line) {
2292
3303
  const tokens = this.tokens(text, "node", line);
3304
+ const { k, pos } = this.vertexNumber(tokens, line);
3305
+ let i = 1;
3306
+ let label = null;
3307
+ if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
3308
+ label = this.labelOf(tokens[1], k, line);
3309
+ i = 2;
3310
+ }
3311
+ const { xyz, dims, next } = this.vertexCoordinates(tokens, i, k);
3312
+ i = next;
3313
+ this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
3314
+ let shape = null;
3315
+ if (i < tokens.length && isShapeKeyword(tokens[i])) {
3316
+ shape = tokens[i].toLowerCase();
3317
+ i++;
3318
+ }
3319
+ const extras = this.extras(tokens, i, "node", line);
3320
+ shape = extras.shape ?? shape;
3321
+ const restored = this.restoredId(extras);
3322
+ this.createNodes();
3323
+ const repeated = this.markVertexSeen(pos, k, line);
3324
+ const index = this.vertexIndex(pos, k, label, restored, repeated, line);
3325
+ if (shape === null && dims > 0 && extras.keys.length > 0 && VOIDING_KEYS.has(extras.keys[0])) {
3326
+ this.voided.push(index);
3327
+ }
3328
+ if (label !== null) {
3329
+ this.labelHandle = this.nodeHandle(this.labelHandle, LABEL_DECL, line);
3330
+ this.sink.setNodeValue(this.labelHandle, index, label);
3331
+ }
3332
+ if (dims > 0) {
3333
+ this.writePosition(index, dims, xyz, k, line);
3334
+ }
3335
+ if (shape !== null) {
3336
+ this.writeShape(index, shape, line);
3337
+ }
3338
+ for (let p = 0; p < extras.keys.length; p++) {
3339
+ this.writeParameter("node", extras.keys[p], index, extras.values[p]);
3340
+ }
3341
+ if (extras.spells !== null) {
3342
+ this.nodeSpellsHandle = this.nodeHandle(this.nodeSpellsHandle, spellsDecl(), line);
3343
+ this.sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
3344
+ }
3345
+ }
3346
+ /**
3347
+ * A vertex line's number, checked: it starts the line and is in the declared range.
3348
+ * @param tokens - the line's tokens
3349
+ * @param line - the line number
3350
+ * @returns the vertex number and its position
3351
+ */
3352
+ vertexNumber(tokens, line) {
2293
3353
  if (!isVertexNumber(tokens[0])) {
2294
3354
  this.report.counts.skippedNodes++;
2295
3355
  throw new LineError(
@@ -2312,27 +3372,25 @@ class PajekParser {
2312
3372
  `vertex ${k} is outside ${this.base}..${this.base + this.vertexCount - 1}`
2313
3373
  );
2314
3374
  }
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;
3375
+ return { k, pos };
3376
+ }
3377
+ /**
3378
+ * A vertex line's coordinates: two or three numbers, or none; a single one is an error.
3379
+ * @param tokens - the line's tokens
3380
+ * @param i - where the coordinates would start
3381
+ * @param k - the vertex number
3382
+ * @returns x, y and z (0 when absent), how many were read, and the index after them
3383
+ */
3384
+ vertexCoordinates(tokens, i, k) {
2325
3385
  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;
3386
+ const x = Number(tokens[i]);
3387
+ const y = Number(tokens[i + 1]);
3388
+ if (i + 2 < tokens.length && isNumericText(tokens[i + 2])) {
3389
+ return { xyz: [x, y, Number(tokens[i + 2])], dims: 3, next: i + 3 };
2334
3390
  }
2335
- } else if (i < tokens.length && isNumericText(tokens[i])) {
3391
+ return { xyz: [x, y, 0], dims: 2, next: i + 2 };
3392
+ }
3393
+ if (i < tokens.length && isNumericText(tokens[i])) {
2336
3394
  this.report.counts.skippedNodes++;
2337
3395
  throw new LineError(
2338
3396
  "parse-error",
@@ -2340,81 +3398,88 @@ class PajekParser {
2340
3398
  `vertex ${k}: a single coordinate "${tokens[i]}"; coordinates are x y [z]`
2341
3399
  );
2342
3400
  }
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) {
3401
+ return { xyz: [0, 0, 0], dims: 0, next: i };
3402
+ }
3403
+ /**
3404
+ * Marks a vertex's position as having a line, warning when it already had one.
3405
+ * @param pos - the vertex's position
3406
+ * @param k - the vertex number
3407
+ * @param line - the line number
3408
+ * @returns whether the vertex already had a line
3409
+ */
3410
+ markVertexSeen(pos, k, line) {
3411
+ if (this.seen[pos] !== 0) {
2355
3412
  this.report.warning(
2356
3413
  "merged",
2357
3414
  PAJEK_ISSUE.DUPLICATE_NODE,
2358
3415
  `vertex ${k} has more than one line; the later values overwrite`,
2359
3416
  { line, element: String(k) }
2360
3417
  );
2361
- } else {
2362
- this.seen[pos] = 1;
2363
- this.seenCount++;
3418
+ return true;
2364
3419
  }
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) {
3420
+ this.seen[pos] = 1;
3421
+ this.seenCount++;
3422
+ return false;
3423
+ }
3424
+ /**
3425
+ * The node index a vertex line writes to, creating the node when its id is deferred to its line.
3426
+ * @param pos - the vertex's position
3427
+ * @param k - the vertex number
3428
+ * @param label - the line's label, or null
3429
+ * @param restored - the original id the line carries, or null
3430
+ * @param repeated - whether the vertex already had a line
3431
+ * @param line - the line number
3432
+ * @returns the node index
3433
+ */
3434
+ vertexIndex(pos, k, label, restored, repeated, line) {
3435
+ const { idOfPos } = this;
3436
+ if (idOfPos !== null && !repeated && this.options.nodeIdFrom === "label") {
3437
+ return this.deferredNode(idOfPos, pos, k, label, line, "label");
3438
+ }
3439
+ if (idOfPos !== null && idOfPos[pos] === void 0) {
2369
3440
  for (let p = this.filledBelow; p < pos; p++) {
2370
- if (this.idOfPos[p] === void 0) {
2371
- this.numberedNode(this.idOfPos, p);
3441
+ if (idOfPos[p] === void 0) {
3442
+ this.numberedNode(idOfPos, p);
2372
3443
  }
2373
3444
  }
2374
3445
  if (pos > this.filledBelow) {
2375
3446
  this.filledBelow = pos;
2376
3447
  }
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);
3448
+ return this.deferredNode(idOfPos, pos, k, restored, line, "originalId");
2395
3449
  }
2396
- if (dims > 0) {
2397
- this.writePosition(index, dims, [x, y, z], k, line);
2398
- }
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]);
3450
+ if (restored !== null && !repeated) {
3451
+ this.report.warning(
3452
+ "coercion",
3453
+ PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
3454
+ `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`,
3455
+ { line, element: String(k) }
3456
+ );
2411
3457
  }
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);
3458
+ return this.indexOfPos[pos];
3459
+ }
3460
+ /**
3461
+ * A node column's handle, declared on first use.
3462
+ * @param handle - the handle so far, or INVALID_INDEX
3463
+ * @param decl - the column's declaration
3464
+ * @param line - the line number
3465
+ * @returns the handle
3466
+ */
3467
+ nodeHandle(handle, decl, line) {
3468
+ return handle === INVALID_INDEX ? declareResolved(this.sink, "node", decl, this.report, { line }).handle : handle;
3469
+ }
3470
+ /**
3471
+ * Writes a vertex's shape keyword: to the shape column, or to an earlier `shape "<text>"` parameter's column.
3472
+ * @param index - the node index
3473
+ * @param shape - the keyword
3474
+ * @param line - the line number
3475
+ */
3476
+ writeShape(index, shape, line) {
3477
+ if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
3478
+ this.writeParameter("node", SHAPE_COLUMN, index, shape);
3479
+ return;
2417
3480
  }
3481
+ this.shapeHandle = this.nodeHandle(this.shapeHandle, SHAPE_DECL, line);
3482
+ this.sink.setNodeValue(this.shapeHandle, index, shape);
2418
3483
  }
2419
3484
  /**
2420
3485
  * A vertex label as written, its character references decoded.
@@ -2475,7 +3540,9 @@ class PajekParser {
2475
3540
  writePosition(index, dims, point, k, line) {
2476
3541
  if (this.positionHandle === INVALID_INDEX) {
2477
3542
  this.coordDims = dims;
2478
- this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims), this.report, { line }).handle;
3543
+ this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims, this.window), this.report, {
3544
+ line
3545
+ }).handle;
2479
3546
  } else if (dims !== this.coordDims) {
2480
3547
  this.report.warnOnce(
2481
3548
  "validation-error",
@@ -2862,7 +3929,7 @@ class PajekParser {
2862
3929
  for (let i = start; i < tokens.length; ) {
2863
3930
  const token = tokens[i];
2864
3931
  if (token.startsWith("[")) {
2865
- extras.spells = this.intervals(token, domain);
3932
+ extras.spells = this.intervals(token, domain, line);
2866
3933
  i++;
2867
3934
  continue;
2868
3935
  }
@@ -2885,8 +3952,9 @@ class PajekParser {
2885
3952
  }
2886
3953
  seen.add(token);
2887
3954
  extras.keys.push(token);
2888
- extras.values.push(tokens[i + 1]);
2889
- i += 2;
3955
+ const triple = COLOR_KEYS.has(token) ? colorTriple(tokens, i + 1) : null;
3956
+ extras.values.push(triple ?? tokens[i + 1]);
3957
+ i += triple === null ? 2 : 4;
2890
3958
  }
2891
3959
  return extras;
2892
3960
  }
@@ -2915,12 +3983,15 @@ class PajekParser {
2915
3983
  );
2916
3984
  }
2917
3985
  /**
2918
- * The spells of a row's interval token; a malformed one skips the row.
3986
+ * The spells of a row's interval token. A token not closed by "]" skips the row; a closed one
3987
+ * whose times cannot be read (`[287-?]`, lin-rel4.net) is reported and dropped, and the rest of
3988
+ * the row (its label, coordinates and parameters) is kept.
2919
3989
  * @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
3990
+ * @param domain - what is skipped when the token is not closed
3991
+ * @param line - the line number
3992
+ * @returns the spells, or null for an empty `[]`, which is no spell at all, and for a dropped one
2922
3993
  */
2923
- intervals(token, domain) {
3994
+ intervals(token, domain, line) {
2924
3995
  if (!isIntervalToken(token)) {
2925
3996
  this.skip(domain);
2926
3997
  throw new LineError(
@@ -2933,12 +4004,13 @@ class PajekParser {
2933
4004
  const spells = parseIntervals(token);
2934
4005
  return spells.length === 0 ? null : spells;
2935
4006
  } catch (err) {
2936
- this.skip(domain);
2937
- throw new LineError(
4007
+ this.report.error(
2938
4008
  "validation-error",
2939
4009
  PAJEK_ISSUE.INTERVAL,
2940
- err instanceof Error ? err.message : String(err)
4010
+ `${err instanceof Error ? err.message : String(err)}; the interval is dropped and the rest of the line kept`,
4011
+ { line }
2941
4012
  );
4013
+ return null;
2942
4014
  }
2943
4015
  }
2944
4016
  /**
@@ -2976,6 +4048,12 @@ class PajekParser {
2976
4048
  writer.write(row, text);
2977
4049
  }
2978
4050
  }
4051
+ const COLOR_KEYS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
4052
+ function colorTriple(tokens, at) {
4053
+ const parts = tokens.slice(at, at + 3);
4054
+ const fraction = (t) => /^[01]?(?:\.\d+)?$/.test(t) && t !== "" && Number(t) <= 1;
4055
+ return parts.length === 3 && parts.every(fraction) ? parts.join(" ") : null;
4056
+ }
2979
4057
  function startsWithCoordinates(text, tokens) {
2980
4058
  if (quotedAfterNumber(text, tokens)) {
2981
4059
  return false;
@@ -3015,10 +4093,29 @@ function headSection(text) {
3015
4093
  }
3016
4094
  const pajekImporter = Object.freeze({
3017
4095
  format: "pajek",
3018
- options: Object.freeze(["firstVertex"]),
4096
+ options: Object.freeze(["firstVertex", "pajekDraw"]),
3019
4097
  extensions: Object.freeze([".net", ".paj"]),
3020
4098
  mimeTypes: Object.freeze(["text/x-pajek", "text/plain"]),
3021
4099
  styles: pajekStyles,
4100
+ /**
4101
+ * Where Pajek 6.02 draws a network whose vertices have no coordinates: round a circle in vertex order, the first
4102
+ * on the left, the rest going clockwise on screen (y down), at radius 0.4 about the middle of the Draw window
4103
+ * (pajek-iliad: 311 vertices 200 points from the middle of its 500-point window). A file with coordinates is read
4104
+ * from its position column.
4105
+ * @param snapshot - the imported graph
4106
+ * @returns the circle for a file with no coordinates, else null
4107
+ */
4108
+ positions(snapshot) {
4109
+ if (snapshot.nodes.byRole("position") !== null) {
4110
+ return null;
4111
+ }
4112
+ return {
4113
+ units: "file",
4114
+ pxPerUnit: PAJEK_POINTS_PER_UNIT,
4115
+ yAxis: "down",
4116
+ unplacedCircle: { center: [0.5, 0.5], radius: 0.4, startDegrees: 180, direction: 1 }
4117
+ };
4118
+ },
3022
4119
  /**
3023
4120
  * Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`),
3024
4121
  * after any `%` comment lines.
@@ -3046,10 +4143,11 @@ const pajekImporter = Object.freeze({
3046
4143
  }
3047
4144
  const resolved = resolveImportOptions(options, DEFAULTS);
3048
4145
  const firstVertex = firstVertexOption(options?.firstVertex);
4146
+ const draw = resolvePajekDraw(options?.pajekDraw);
3049
4147
  const report = new ImportReportBuilder("pajek", resolved.errorLimit);
3050
4148
  reportSinkOptions(sink, options, report);
3051
4149
  reportUnusedOptions(options, report, USED_OPTIONS);
3052
- const parser = new PajekParser(sink, report, resolved, firstVertex);
4150
+ const parser = new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
3053
4151
  const reader = new LineReader(input, report, resolved);
3054
4152
  let rest = null;
3055
4153
  let restLine = 0;
@@ -3069,6 +4167,9 @@ const pajekImporter = Object.freeze({
3069
4167
  }
3070
4168
  }
3071
4169
  parser.finish();
4170
+ if (draw !== null || parser.voided.length > 0) {
4171
+ report.keepForStyles({ block: parser.keptBlock, pajekDraw: draw ?? void 0, voided: parser.voided });
4172
+ }
3072
4173
  if (rest !== null) {
3073
4174
  const objects = rest.objects > 0 ? `; ${rest.objects} *Partition / *Vector object(s) after them are not read` : "";
3074
4175
  report.warning(
@@ -3093,13 +4194,25 @@ const pajekImporter = Object.freeze({
3093
4194
  async importAll(input, sinkFor, options) {
3094
4195
  const resolved = resolveImportOptions(options, DEFAULTS);
3095
4196
  const firstVertex = firstVertexOption(options?.firstVertex);
4197
+ const draw = resolvePajekDraw(options?.pajekDraw);
3096
4198
  const reports = [new ImportReportBuilder("pajek", resolved.errorLimit)];
3097
4199
  reportUnusedOptions(options, reports[0], USED_OPTIONS);
3098
4200
  const open = () => {
3099
4201
  const report = reports[reports.length - 1];
3100
4202
  const sink = sinkFor(reports.length - 1);
3101
4203
  reportSinkOptions(sink, options, report);
3102
- return new PajekParser(sink, report, resolved, firstVertex);
4204
+ return new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
4205
+ };
4206
+ const close = (p) => {
4207
+ p.finish();
4208
+ const last = reports.at(-1);
4209
+ if (last !== void 0 && (draw !== null || p.voided.length > 0)) {
4210
+ last.keepForStyles({
4211
+ block: p.keptBlock,
4212
+ pajekDraw: draw ?? void 0,
4213
+ voided: p.voided
4214
+ });
4215
+ }
3103
4216
  };
3104
4217
  let parser = open();
3105
4218
  const reader = new LineReader(input, reports[0], resolved);
@@ -3107,7 +4220,7 @@ const pajekImporter = Object.freeze({
3107
4220
  for await (const raw of reader) {
3108
4221
  const text = withoutStrayBom(raw);
3109
4222
  if (parser.line(text, reader.line)) {
3110
- parser.finish();
4223
+ close(parser);
3111
4224
  reports.push(new ImportReportBuilder("pajek", resolved.errorLimit));
3112
4225
  parser = open();
3113
4226
  parser.line(text, reader.line);
@@ -3117,7 +4230,7 @@ const pajekImporter = Object.freeze({
3117
4230
  throwIfAborted(resolved.signal);
3118
4231
  }
3119
4232
  }
3120
- parser.finish();
4233
+ close(parser);
3121
4234
  throwIfAborted(resolved.signal);
3122
4235
  return reports.map((r) => r.finish());
3123
4236
  }
@@ -3179,4 +4292,4 @@ export {
3179
4292
  pajekImporter as d,
3180
4293
  pajekExporter as p
3181
4294
  };
3182
- //# sourceMappingURL=importer-CVT-JyDE.js.map
4295
+ //# sourceMappingURL=importer-vRq4h3j5.js.map