@graphty/graph-io 0.0.0 → 0.2.0

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 (339) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +250 -28
  3. package/dist/chunks/children-CL3Cy0ez.js +238 -0
  4. package/dist/chunks/children-CL3Cy0ez.js.map +1 -0
  5. package/dist/chunks/escape-DyI8JofU.js +938 -0
  6. package/dist/chunks/escape-DyI8JofU.js.map +1 -0
  7. package/dist/chunks/importer-CQnJuWJw.js +2987 -0
  8. package/dist/chunks/importer-CQnJuWJw.js.map +1 -0
  9. package/dist/chunks/importer-CpCpfbxr.js +2015 -0
  10. package/dist/chunks/importer-CpCpfbxr.js.map +1 -0
  11. package/dist/chunks/importer-DbnGYr3_.js +2342 -0
  12. package/dist/chunks/importer-DbnGYr3_.js.map +1 -0
  13. package/dist/chunks/importer-GozH8DkN.js +3050 -0
  14. package/dist/chunks/importer-GozH8DkN.js.map +1 -0
  15. package/dist/chunks/records-CGpxszm1.js +605 -0
  16. package/dist/chunks/records-CGpxszm1.js.map +1 -0
  17. package/dist/chunks/text-CajMdVFy.js +189 -0
  18. package/dist/chunks/text-CajMdVFy.js.map +1 -0
  19. package/dist/chunks/writer-DxSKC7TL.js +2842 -0
  20. package/dist/chunks/writer-DxSKC7TL.js.map +1 -0
  21. package/dist/csv.d.ts +1 -0
  22. package/dist/csv.js +1702 -0
  23. package/dist/csv.js.map +1 -0
  24. package/dist/dot.d.ts +1 -0
  25. package/dist/dot.js +8 -0
  26. package/dist/dot.js.map +1 -0
  27. package/dist/gexf.d.ts +1 -0
  28. package/dist/gexf.js +3466 -0
  29. package/dist/gexf.js.map +1 -0
  30. package/dist/gml.d.ts +1 -0
  31. package/dist/gml.js +2647 -0
  32. package/dist/gml.js.map +1 -0
  33. package/dist/graph-io.d.ts +1 -0
  34. package/dist/graph-io.js +790 -0
  35. package/dist/graph-io.js.map +1 -0
  36. package/dist/graphml.d.ts +1 -0
  37. package/dist/graphml.js +8 -0
  38. package/dist/graphml.js.map +1 -0
  39. package/dist/json.d.ts +1 -0
  40. package/dist/json.js +11 -0
  41. package/dist/json.js.map +1 -0
  42. package/dist/neo4j.d.ts +1 -0
  43. package/dist/neo4j.js +2046 -0
  44. package/dist/neo4j.js.map +1 -0
  45. package/dist/pajek.d.ts +1 -0
  46. package/dist/pajek.js +8 -0
  47. package/dist/pajek.js.map +1 -0
  48. package/dist/src/children.d.ts +134 -0
  49. package/dist/src/children.d.ts.map +1 -0
  50. package/dist/src/children.js +274 -0
  51. package/dist/src/children.js.map +1 -0
  52. package/dist/src/common/attributes.d.ts +229 -0
  53. package/dist/src/common/attributes.d.ts.map +1 -0
  54. package/dist/src/common/attributes.js +368 -0
  55. package/dist/src/common/attributes.js.map +1 -0
  56. package/dist/src/common/codes.d.ts +105 -0
  57. package/dist/src/common/codes.d.ts.map +1 -0
  58. package/dist/src/common/codes.js +107 -0
  59. package/dist/src/common/codes.js.map +1 -0
  60. package/dist/src/common/declared-types.d.ts +84 -0
  61. package/dist/src/common/declared-types.d.ts.map +1 -0
  62. package/dist/src/common/declared-types.js +326 -0
  63. package/dist/src/common/declared-types.js.map +1 -0
  64. package/dist/src/common/direction.d.ts +206 -0
  65. package/dist/src/common/direction.d.ts.map +1 -0
  66. package/dist/src/common/direction.js +370 -0
  67. package/dist/src/common/direction.js.map +1 -0
  68. package/dist/src/common/escape.d.ts +92 -0
  69. package/dist/src/common/escape.d.ts.map +1 -0
  70. package/dist/src/common/escape.js +212 -0
  71. package/dist/src/common/escape.js.map +1 -0
  72. package/dist/src/common/export.d.ts +249 -0
  73. package/dist/src/common/export.d.ts.map +1 -0
  74. package/dist/src/common/export.js +594 -0
  75. package/dist/src/common/export.js.map +1 -0
  76. package/dist/src/common/format.d.ts +59 -0
  77. package/dist/src/common/format.d.ts.map +1 -0
  78. package/dist/src/common/format.js +106 -0
  79. package/dist/src/common/format.js.map +1 -0
  80. package/dist/src/common/ids.d.ts +83 -0
  81. package/dist/src/common/ids.d.ts.map +1 -0
  82. package/dist/src/common/ids.js +158 -0
  83. package/dist/src/common/ids.js.map +1 -0
  84. package/dist/src/common/input.d.ts +100 -0
  85. package/dist/src/common/input.d.ts.map +1 -0
  86. package/dist/src/common/input.js +335 -0
  87. package/dist/src/common/input.js.map +1 -0
  88. package/dist/src/common/lists.d.ts +34 -0
  89. package/dist/src/common/lists.d.ts.map +1 -0
  90. package/dist/src/common/lists.js +185 -0
  91. package/dist/src/common/lists.js.map +1 -0
  92. package/dist/src/common/options.d.ts +108 -0
  93. package/dist/src/common/options.d.ts.map +1 -0
  94. package/dist/src/common/options.js +265 -0
  95. package/dist/src/common/options.js.map +1 -0
  96. package/dist/src/common/report.d.ts +187 -0
  97. package/dist/src/common/report.d.ts.map +1 -0
  98. package/dist/src/common/report.js +274 -0
  99. package/dist/src/common/report.js.map +1 -0
  100. package/dist/src/common/temporal.d.ts +71 -0
  101. package/dist/src/common/temporal.d.ts.map +1 -0
  102. package/dist/src/common/temporal.js +266 -0
  103. package/dist/src/common/temporal.js.map +1 -0
  104. package/dist/src/common/text.d.ts +104 -0
  105. package/dist/src/common/text.d.ts.map +1 -0
  106. package/dist/src/common/text.js +255 -0
  107. package/dist/src/common/text.js.map +1 -0
  108. package/dist/src/common/weights.d.ts +77 -0
  109. package/dist/src/common/weights.d.ts.map +1 -0
  110. package/dist/src/common/weights.js +156 -0
  111. package/dist/src/common/weights.js.map +1 -0
  112. package/dist/src/common/writer.d.ts +51 -0
  113. package/dist/src/common/writer.d.ts.map +1 -0
  114. package/dist/src/common/writer.js +108 -0
  115. package/dist/src/common/writer.js.map +1 -0
  116. package/dist/src/common/xml.d.ts +245 -0
  117. package/dist/src/common/xml.d.ts.map +1 -0
  118. package/dist/src/common/xml.js +942 -0
  119. package/dist/src/common/xml.js.map +1 -0
  120. package/dist/src/formats/csv/exporter.d.ts +70 -0
  121. package/dist/src/formats/csv/exporter.d.ts.map +1 -0
  122. package/dist/src/formats/csv/exporter.js +682 -0
  123. package/dist/src/formats/csv/exporter.js.map +1 -0
  124. package/dist/src/formats/csv/header.d.ts +66 -0
  125. package/dist/src/formats/csv/header.d.ts.map +1 -0
  126. package/dist/src/formats/csv/header.js +152 -0
  127. package/dist/src/formats/csv/header.js.map +1 -0
  128. package/dist/src/formats/csv/importer.d.ts +82 -0
  129. package/dist/src/formats/csv/importer.d.ts.map +1 -0
  130. package/dist/src/formats/csv/importer.js +849 -0
  131. package/dist/src/formats/csv/importer.js.map +1 -0
  132. package/dist/src/formats/csv/index.d.ts +60 -0
  133. package/dist/src/formats/csv/index.d.ts.map +1 -0
  134. package/dist/src/formats/csv/index.js +63 -0
  135. package/dist/src/formats/csv/index.js.map +1 -0
  136. package/dist/src/formats/csv/records.d.ts +188 -0
  137. package/dist/src/formats/csv/records.d.ts.map +1 -0
  138. package/dist/src/formats/csv/records.js +702 -0
  139. package/dist/src/formats/csv/records.js.map +1 -0
  140. package/dist/src/formats/csv/values.d.ts +105 -0
  141. package/dist/src/formats/csv/values.d.ts.map +1 -0
  142. package/dist/src/formats/csv/values.js +192 -0
  143. package/dist/src/formats/csv/values.js.map +1 -0
  144. package/dist/src/formats/dot/exporter.d.ts +52 -0
  145. package/dist/src/formats/dot/exporter.d.ts.map +1 -0
  146. package/dist/src/formats/dot/exporter.js +836 -0
  147. package/dist/src/formats/dot/exporter.js.map +1 -0
  148. package/dist/src/formats/dot/importer.d.ts +102 -0
  149. package/dist/src/formats/dot/importer.d.ts.map +1 -0
  150. package/dist/src/formats/dot/importer.js +1291 -0
  151. package/dist/src/formats/dot/importer.js.map +1 -0
  152. package/dist/src/formats/dot/index.d.ts +7 -0
  153. package/dist/src/formats/dot/index.d.ts.map +1 -0
  154. package/dist/src/formats/dot/index.js +7 -0
  155. package/dist/src/formats/dot/index.js.map +1 -0
  156. package/dist/src/formats/dot/names.d.ts +29 -0
  157. package/dist/src/formats/dot/names.d.ts.map +1 -0
  158. package/dist/src/formats/dot/names.js +28 -0
  159. package/dist/src/formats/dot/names.js.map +1 -0
  160. package/dist/src/formats/dot/tokenizer.d.ts +114 -0
  161. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -0
  162. package/dist/src/formats/dot/tokenizer.js +341 -0
  163. package/dist/src/formats/dot/tokenizer.js.map +1 -0
  164. package/dist/src/formats/gexf/exporter.d.ts +56 -0
  165. package/dist/src/formats/gexf/exporter.d.ts.map +1 -0
  166. package/dist/src/formats/gexf/exporter.js +1395 -0
  167. package/dist/src/formats/gexf/exporter.js.map +1 -0
  168. package/dist/src/formats/gexf/importer.d.ts +73 -0
  169. package/dist/src/formats/gexf/importer.d.ts.map +1 -0
  170. package/dist/src/formats/gexf/importer.js +1880 -0
  171. package/dist/src/formats/gexf/importer.js.map +1 -0
  172. package/dist/src/formats/gexf/index.d.ts +96 -0
  173. package/dist/src/formats/gexf/index.d.ts.map +1 -0
  174. package/dist/src/formats/gexf/index.js +97 -0
  175. package/dist/src/formats/gexf/index.js.map +1 -0
  176. package/dist/src/formats/gexf/schema.d.ts +135 -0
  177. package/dist/src/formats/gexf/schema.d.ts.map +1 -0
  178. package/dist/src/formats/gexf/schema.js +323 -0
  179. package/dist/src/formats/gexf/schema.js.map +1 -0
  180. package/dist/src/formats/gml/exporter.d.ts +69 -0
  181. package/dist/src/formats/gml/exporter.d.ts.map +1 -0
  182. package/dist/src/formats/gml/exporter.js +1093 -0
  183. package/dist/src/formats/gml/exporter.js.map +1 -0
  184. package/dist/src/formats/gml/importer.d.ts +66 -0
  185. package/dist/src/formats/gml/importer.d.ts.map +1 -0
  186. package/dist/src/formats/gml/importer.js +1331 -0
  187. package/dist/src/formats/gml/importer.js.map +1 -0
  188. package/dist/src/formats/gml/index.d.ts +85 -0
  189. package/dist/src/formats/gml/index.d.ts.map +1 -0
  190. package/dist/src/formats/gml/index.js +88 -0
  191. package/dist/src/formats/gml/index.js.map +1 -0
  192. package/dist/src/formats/gml/syntax.d.ts +186 -0
  193. package/dist/src/formats/gml/syntax.d.ts.map +1 -0
  194. package/dist/src/formats/gml/syntax.js +467 -0
  195. package/dist/src/formats/gml/syntax.js.map +1 -0
  196. package/dist/src/formats/graphml/constants.d.ts +169 -0
  197. package/dist/src/formats/graphml/constants.d.ts.map +1 -0
  198. package/dist/src/formats/graphml/constants.js +165 -0
  199. package/dist/src/formats/graphml/constants.js.map +1 -0
  200. package/dist/src/formats/graphml/exporter.d.ts +34 -0
  201. package/dist/src/formats/graphml/exporter.d.ts.map +1 -0
  202. package/dist/src/formats/graphml/exporter.js +1176 -0
  203. package/dist/src/formats/graphml/exporter.js.map +1 -0
  204. package/dist/src/formats/graphml/importer.d.ts +31 -0
  205. package/dist/src/formats/graphml/importer.d.ts.map +1 -0
  206. package/dist/src/formats/graphml/importer.js +1607 -0
  207. package/dist/src/formats/graphml/importer.js.map +1 -0
  208. package/dist/src/formats/graphml/index.d.ts +8 -0
  209. package/dist/src/formats/graphml/index.d.ts.map +1 -0
  210. package/dist/src/formats/graphml/index.js +8 -0
  211. package/dist/src/formats/graphml/index.js.map +1 -0
  212. package/dist/src/formats/graphml/tree.d.ts +72 -0
  213. package/dist/src/formats/graphml/tree.d.ts.map +1 -0
  214. package/dist/src/formats/graphml/tree.js +290 -0
  215. package/dist/src/formats/graphml/tree.js.map +1 -0
  216. package/dist/src/formats/json/dialect.d.ts +125 -0
  217. package/dist/src/formats/json/dialect.d.ts.map +1 -0
  218. package/dist/src/formats/json/dialect.js +262 -0
  219. package/dist/src/formats/json/dialect.js.map +1 -0
  220. package/dist/src/formats/json/exporter.d.ts +89 -0
  221. package/dist/src/formats/json/exporter.d.ts.map +1 -0
  222. package/dist/src/formats/json/exporter.js +1358 -0
  223. package/dist/src/formats/json/exporter.js.map +1 -0
  224. package/dist/src/formats/json/importer.d.ts +108 -0
  225. package/dist/src/formats/json/importer.d.ts.map +1 -0
  226. package/dist/src/formats/json/importer.js +1838 -0
  227. package/dist/src/formats/json/importer.js.map +1 -0
  228. package/dist/src/formats/json/index.d.ts +8 -0
  229. package/dist/src/formats/json/index.d.ts.map +1 -0
  230. package/dist/src/formats/json/index.js +8 -0
  231. package/dist/src/formats/json/index.js.map +1 -0
  232. package/dist/src/formats/neo4j/exporter.d.ts +68 -0
  233. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -0
  234. package/dist/src/formats/neo4j/exporter.js +1055 -0
  235. package/dist/src/formats/neo4j/exporter.js.map +1 -0
  236. package/dist/src/formats/neo4j/header.d.ts +52 -0
  237. package/dist/src/formats/neo4j/header.d.ts.map +1 -0
  238. package/dist/src/formats/neo4j/header.js +131 -0
  239. package/dist/src/formats/neo4j/header.js.map +1 -0
  240. package/dist/src/formats/neo4j/importer.d.ts +73 -0
  241. package/dist/src/formats/neo4j/importer.d.ts.map +1 -0
  242. package/dist/src/formats/neo4j/importer.js +932 -0
  243. package/dist/src/formats/neo4j/importer.js.map +1 -0
  244. package/dist/src/formats/neo4j/index.d.ts +79 -0
  245. package/dist/src/formats/neo4j/index.d.ts.map +1 -0
  246. package/dist/src/formats/neo4j/index.js +83 -0
  247. package/dist/src/formats/neo4j/index.js.map +1 -0
  248. package/dist/src/formats/pajek/exporter.d.ts +58 -0
  249. package/dist/src/formats/pajek/exporter.d.ts.map +1 -0
  250. package/dist/src/formats/pajek/exporter.js +825 -0
  251. package/dist/src/formats/pajek/exporter.js.map +1 -0
  252. package/dist/src/formats/pajek/importer.d.ts +88 -0
  253. package/dist/src/formats/pajek/importer.d.ts.map +1 -0
  254. package/dist/src/formats/pajek/importer.js +1047 -0
  255. package/dist/src/formats/pajek/importer.js.map +1 -0
  256. package/dist/src/formats/pajek/index.d.ts +7 -0
  257. package/dist/src/formats/pajek/index.d.ts.map +1 -0
  258. package/dist/src/formats/pajek/index.js +7 -0
  259. package/dist/src/formats/pajek/index.js.map +1 -0
  260. package/dist/src/formats/pajek/syntax.d.ts +112 -0
  261. package/dist/src/formats/pajek/syntax.d.ts.map +1 -0
  262. package/dist/src/formats/pajek/syntax.js +269 -0
  263. package/dist/src/formats/pajek/syntax.js.map +1 -0
  264. package/dist/src/index.d.ts +35 -0
  265. package/dist/src/index.d.ts.map +1 -0
  266. package/dist/src/index.js +39 -0
  267. package/dist/src/index.js.map +1 -0
  268. package/dist/src/registry.d.ts +207 -0
  269. package/dist/src/registry.d.ts.map +1 -0
  270. package/dist/src/registry.js +481 -0
  271. package/dist/src/registry.js.map +1 -0
  272. package/dist/src/sniff.d.ts +104 -0
  273. package/dist/src/sniff.d.ts.map +1 -0
  274. package/dist/src/sniff.js +357 -0
  275. package/dist/src/sniff.js.map +1 -0
  276. package/dist/src/types.d.ts +238 -0
  277. package/dist/src/types.d.ts.map +1 -0
  278. package/dist/src/types.js +29 -0
  279. package/dist/src/types.js.map +1 -0
  280. package/dist/tsconfig.build.tsbuildinfo +1 -0
  281. package/package.json +122 -7
  282. package/src/children.ts +335 -0
  283. package/src/common/attributes.ts +520 -0
  284. package/src/common/codes.ts +153 -0
  285. package/src/common/declared-types.ts +374 -0
  286. package/src/common/direction.ts +518 -0
  287. package/src/common/escape.ts +231 -0
  288. package/src/common/export.ts +817 -0
  289. package/src/common/format.ts +111 -0
  290. package/src/common/ids.ts +176 -0
  291. package/src/common/input.ts +378 -0
  292. package/src/common/lists.ts +196 -0
  293. package/src/common/options.ts +377 -0
  294. package/src/common/report.ts +352 -0
  295. package/src/common/temporal.ts +302 -0
  296. package/src/common/text.ts +294 -0
  297. package/src/common/weights.ts +202 -0
  298. package/src/common/writer.ts +123 -0
  299. package/src/common/xml.ts +1053 -0
  300. package/src/formats/csv/exporter.ts +894 -0
  301. package/src/formats/csv/header.ts +172 -0
  302. package/src/formats/csv/importer.ts +1104 -0
  303. package/src/formats/csv/index.ts +88 -0
  304. package/src/formats/csv/records.ts +813 -0
  305. package/src/formats/csv/values.ts +224 -0
  306. package/src/formats/dot/exporter.ts +1014 -0
  307. package/src/formats/dot/importer.ts +1549 -0
  308. package/src/formats/dot/index.ts +7 -0
  309. package/src/formats/dot/names.ts +40 -0
  310. package/src/formats/dot/tokenizer.ts +384 -0
  311. package/src/formats/gexf/exporter.ts +1696 -0
  312. package/src/formats/gexf/importer.ts +2333 -0
  313. package/src/formats/gexf/index.ts +142 -0
  314. package/src/formats/gexf/schema.ts +361 -0
  315. package/src/formats/gml/exporter.ts +1404 -0
  316. package/src/formats/gml/importer.ts +1591 -0
  317. package/src/formats/gml/index.ts +128 -0
  318. package/src/formats/gml/syntax.ts +545 -0
  319. package/src/formats/graphml/constants.ts +225 -0
  320. package/src/formats/graphml/exporter.ts +1458 -0
  321. package/src/formats/graphml/importer.ts +2027 -0
  322. package/src/formats/graphml/index.ts +8 -0
  323. package/src/formats/graphml/tree.ts +318 -0
  324. package/src/formats/json/dialect.ts +317 -0
  325. package/src/formats/json/exporter.ts +1616 -0
  326. package/src/formats/json/importer.ts +2271 -0
  327. package/src/formats/json/index.ts +8 -0
  328. package/src/formats/neo4j/exporter.ts +1287 -0
  329. package/src/formats/neo4j/header.ts +156 -0
  330. package/src/formats/neo4j/importer.ts +1220 -0
  331. package/src/formats/neo4j/index.ts +116 -0
  332. package/src/formats/pajek/exporter.ts +1000 -0
  333. package/src/formats/pajek/importer.ts +1311 -0
  334. package/src/formats/pajek/index.ts +7 -0
  335. package/src/formats/pajek/syntax.ts +307 -0
  336. package/src/index.ts +244 -0
  337. package/src/registry.ts +617 -0
  338. package/src/sniff.ts +397 -0
  339. package/src/types.ts +262 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Direction resolution through the sink (design sections 3.6 and 8.4, decision D-DIR): the
3
+ * importer reads the file's header direction, calls `sink.setDirected()` once before the first
4
+ * edge, then pushes every edge as it is read. Mixed files are handled per `onMixedDirection`:
5
+ *
6
+ * - "expand" (default): an undirected edge into a directed sink becomes two logical edges linked
7
+ * by the `graphty.pair` column with `graphty.directed` = false on both halves; a directed edge
8
+ * into an undirected sink triggers ONE `setDirected(true, { expand: true })`, after which the
9
+ * builder has expanded everything pushed so far and the importer continues in directed mode.
10
+ * - "directed" / "undirected": every edge is treated that way (the distinction is dropped and
11
+ * reported once, with the count).
12
+ * - "error": the first edge whose direction differs from the sink's aborts the import.
13
+ *
14
+ * A locked or non-empty sink wins over the file (design section 8.4 precedence): a refused
15
+ * `setDirected` is recorded as a coercion issue and the importer continues with `sink.directed`,
16
+ * expanding every edge that differs. A GEXF `mutual` edge expands like an undirected one with the
17
+ * additional `graphty.mutual` role column set on its primary half.
18
+ *
19
+ * The reserved columns are declared with exactly the builder's own declarations so that a sink the
20
+ * builder already expanded hands back the existing handles.
21
+ */
22
+ import { GraphFormatError, INVALID_INDEX, } from "@graphty/graph-format";
23
+ import { DIRECTION_FORCED_CODE, DIRECTION_REFUSED_CODE, MIXED_DIRECTION_CODE } from "./codes.js";
24
+ /** The name of the bool edge column marking source-directed edges (design section 3.6). */
25
+ export const DIRECTED_COLUMN = "graphty.directed";
26
+ /** The name of the u32 edge column pairing the halves of an expanded edge (design section 3.6). */
27
+ export const PAIR_COLUMN = "graphty.pair";
28
+ /** The name of the bool edge column marking GEXF mutual edges (design section 3.6). */
29
+ export const MUTUAL_COLUMN = "graphty.mutual";
30
+ export { DIRECTION_FORCED_CODE, DIRECTION_REFUSED_CODE, MIXED_DIRECTION_CODE };
31
+ const DIRECTED_DECL = { name: DIRECTED_COLUMN, dtype: "bool", role: "directed" };
32
+ const PAIR_DECL = { name: PAIR_COLUMN, dtype: "u32", role: "pair", refersTo: "edge" };
33
+ const MUTUAL_DECL = { name: MUTUAL_COLUMN, dtype: "bool", role: "mutual" };
34
+ /**
35
+ * Pushes edges into a sink while resolving direction per design section 8.4. One instance per
36
+ * import call; `setHeader()` before the first `addEdge()`.
37
+ */
38
+ export class DirectionResolver {
39
+ /**
40
+ * Create a resolver.
41
+ * @param sink - the sink edges are pushed into
42
+ * @param report - the report issues are recorded in
43
+ * @param policy - the resolved onMixedDirection option
44
+ */
45
+ constructor(sink, report, policy) {
46
+ this.directedHandle = INVALID_INDEX;
47
+ this.pairHandle = INVALID_INDEX;
48
+ this.mutualHandle = INVALID_INDEX;
49
+ /** The first edge index this resolver pushed, for the backfill of graphty.directed; -1 before the first. */
50
+ this.firstEdge = -1;
51
+ /** The next edge index this resolver expects to receive (contiguity between compactions, I16). */
52
+ this.nextEdge = -1;
53
+ this.forcedCount = 0;
54
+ this.headerSet = false;
55
+ this.mirrorOfLast = INVALID_INDEX;
56
+ this.sink = sink;
57
+ this.report = report;
58
+ this.policy = policy;
59
+ }
60
+ /**
61
+ * The sink's current direction.
62
+ * @returns true when directed
63
+ */
64
+ get directed() {
65
+ return this.sink.directed;
66
+ }
67
+ /**
68
+ * Whether the reserved direction columns exist (the sink holds expanded edges).
69
+ * @returns true once graphty.pair was declared or adopted
70
+ */
71
+ get expanded() {
72
+ return this.pairHandle !== INVALID_INDEX;
73
+ }
74
+ /**
75
+ * Rule 1 of design section 8.4: set the sink's direction from the file's header (or the
76
+ * `defaultDirected` option for a file that declares none) before the first edge. Under the
77
+ * "directed" / "undirected" policies the policy's direction is used instead and the difference
78
+ * is reported. A refusal (E_DIRECTED: locked, or a non-empty directed sink for an undirected
79
+ * header) is recorded as a coercion issue and the sink's direction stands; a non-empty unlocked
80
+ * undirected sink with a directed header is expanded in place.
81
+ * @param headerDirected - the direction the file declares (or the default)
82
+ * @param where - the line of the header, when known
83
+ */
84
+ setHeader(headerDirected, where) {
85
+ this.headerSet = true;
86
+ let wanted = headerDirected;
87
+ if (this.policy === "directed" || this.policy === "undirected") {
88
+ wanted = this.policy === "directed";
89
+ if (wanted !== headerDirected) {
90
+ this.report.warning("coercion", DIRECTION_FORCED_CODE, `the file declares ${direction(headerDirected)} edges; read as ${direction(wanted)} per onMixedDirection`, { line: where?.line ?? null });
91
+ }
92
+ }
93
+ const { sink } = this;
94
+ if (sink.directed === wanted) {
95
+ this.adoptExisting();
96
+ return;
97
+ }
98
+ try {
99
+ if (wanted && sink.edgeCount > 0 && !sink.directedLocked) {
100
+ const before = sink.edgeCount;
101
+ sink.setDirected(true, { expand: true });
102
+ this.adoptExpansionColumns();
103
+ this.report.counts.expandedMixed += before;
104
+ }
105
+ else {
106
+ sink.setDirected(wanted);
107
+ }
108
+ }
109
+ catch (err) {
110
+ if (!(err instanceof GraphFormatError) || err.code !== "E_DIRECTED") {
111
+ throw err;
112
+ }
113
+ this.report.warning("coercion", DIRECTION_REFUSED_CODE, `the file is ${direction(wanted)} but the sink is ${direction(sink.directed)} (${reasonOf(err)}); read as ${direction(sink.directed)}`, { line: where?.line ?? null });
114
+ }
115
+ this.adoptExisting();
116
+ }
117
+ /**
118
+ * Pick up reserved columns a caller's sink already holds (an earlier expansion), so every edge
119
+ * pushed from now on gets its graphty.directed value.
120
+ */
121
+ adoptExisting() {
122
+ if (this.pairHandle === INVALID_INDEX && this.sink.edgeColumn(PAIR_COLUMN) !== INVALID_INDEX) {
123
+ this.adoptExpansionColumns();
124
+ }
125
+ }
126
+ /**
127
+ * The mirror half of the edge most recently pushed by addEdge(), when it was expanded into a
128
+ * pair; INVALID_INDEX otherwise. An importer that learns an edge's weight after pushing it
129
+ * (a GEXF attvalue) sets it on both halves.
130
+ * @returns the mirror's logical index, or INVALID_INDEX
131
+ */
132
+ get lastMirror() {
133
+ return this.mirrorOfLast;
134
+ }
135
+ /**
136
+ * Rule 2 of design section 8.4: push one source edge. An edge whose direction equals the
137
+ * sink's is one addEdge; one that differs is expanded, forced or refused per the policy.
138
+ * @param source - the source id
139
+ * @param target - the target id
140
+ * @param kind - the edge's direction in the file
141
+ * @param weight - the weight, or undefined when the file gives none
142
+ * @param where - the line and element, for issues
143
+ * @returns the logical index of the (primary) edge
144
+ */
145
+ addEdge(source, target, kind, weight, where) {
146
+ if (!this.headerSet) {
147
+ throw new GraphFormatError("E_DIRECTED", "DirectionResolver.setHeader() must run before the first edge", {
148
+ reason: "header not set",
149
+ });
150
+ }
151
+ const { sink } = this;
152
+ this.mirrorOfLast = INVALID_INDEX;
153
+ const edgeDirected = kind !== "undirected";
154
+ if (edgeDirected === sink.directed && kind !== "mutual") {
155
+ const e = sink.addEdge(source, target, weight);
156
+ this.track(e);
157
+ if (this.directedHandle !== INVALID_INDEX) {
158
+ sink.setEdgeValue(this.directedHandle, e, edgeDirected);
159
+ }
160
+ return e;
161
+ }
162
+ switch (this.policy) {
163
+ case "directed":
164
+ case "undirected": {
165
+ // the sink's direction is the policy's (or a locked sink's); the edge is pushed as the sink's kind
166
+ this.forcedCount++;
167
+ this.report.warnOnce("coercion", DIRECTION_FORCED_CODE, `${kind} edges read as ${direction(sink.directed)} per onMixedDirection`, where);
168
+ const e = sink.addEdge(source, target, weight);
169
+ this.track(e);
170
+ if (this.directedHandle !== INVALID_INDEX) {
171
+ sink.setEdgeValue(this.directedHandle, e, sink.directed);
172
+ }
173
+ return e;
174
+ }
175
+ case "error":
176
+ this.report.error("validation-error", MIXED_DIRECTION_CODE, `${kind} edge in a ${direction(sink.directed)} graph (onMixedDirection: "error")`, where);
177
+ throw this.report.abort("mixed direction refused", { code: MIXED_DIRECTION_CODE });
178
+ case "expand":
179
+ return this.expand(source, target, kind, weight, where);
180
+ default: {
181
+ const name = this.policy;
182
+ throw new GraphFormatError("E_UNSUPPORTED", `unknown onMixedDirection ${name}`, {
183
+ option: "onMixedDirection",
184
+ found: name,
185
+ });
186
+ }
187
+ }
188
+ }
189
+ /**
190
+ * How many edges were pushed with a direction other than their own under the forcing policies.
191
+ * @returns the count
192
+ */
193
+ get forced() {
194
+ return this.forcedCount;
195
+ }
196
+ /**
197
+ * Expand one edge that differs from the sink's direction.
198
+ * @param source - the source id
199
+ * @param target - the target id
200
+ * @param kind - the edge's direction in the file
201
+ * @param weight - the weight, or undefined
202
+ * @param where - the line and element, for issues
203
+ * @returns the primary edge index
204
+ */
205
+ expand(source, target, kind, weight, where) {
206
+ const { sink } = this;
207
+ if (!sink.directed) {
208
+ // a directed (or mutual) edge into an undirected sink: expand the sink once
209
+ try {
210
+ const before = sink.edgeCount;
211
+ sink.setDirected(true, { expand: true });
212
+ this.adoptExpansionColumns();
213
+ this.report.counts.expandedMixed += before;
214
+ }
215
+ catch (err) {
216
+ if (!(err instanceof GraphFormatError) || err.code !== "E_DIRECTED") {
217
+ throw err;
218
+ }
219
+ this.report.error("coercion", DIRECTION_REFUSED_CODE, `${direction(true)} edge in a locked ${direction(false)} sink cannot be expanded`, where);
220
+ throw this.report.abort("the sink refused the expansion to directed", {
221
+ code: DIRECTION_REFUSED_CODE,
222
+ reason: err.details.reason,
223
+ });
224
+ }
225
+ if (kind === "directed") {
226
+ const e = sink.addEdge(source, target, weight);
227
+ this.track(e);
228
+ sink.setEdgeValue(this.directedHandle, e, true);
229
+ return e;
230
+ }
231
+ }
232
+ this.ensureExpansionColumns();
233
+ const first = sink.addEdge(source, target, weight);
234
+ this.track(first);
235
+ const mutual = kind === "mutual";
236
+ sink.setEdgeValue(this.directedHandle, first, mutual);
237
+ this.report.counts.expandedMixed++;
238
+ if (mutual) {
239
+ this.ensureMutualColumn();
240
+ sink.setEdgeValue(this.mutualHandle, first, true);
241
+ }
242
+ const u = sink.indexOf(source);
243
+ const v = sink.indexOf(target);
244
+ if (u === v) {
245
+ // an undirected self-loop is one arc (I7); the builder does not mirror it either
246
+ return first;
247
+ }
248
+ const mirror = sink.addEdge(target, source, weight);
249
+ this.track(mirror);
250
+ this.mirrorOfLast = mirror;
251
+ sink.setEdgeValue(this.directedHandle, mirror, mutual);
252
+ sink.setEdgeValue(this.pairHandle, first, mirror);
253
+ sink.setEdgeValue(this.pairHandle, mirror, first);
254
+ return first;
255
+ }
256
+ /**
257
+ * Note an edge index this resolver pushed, for the backfill of graphty.directed.
258
+ * @param e - the edge index
259
+ */
260
+ track(e) {
261
+ if (this.firstEdge < 0) {
262
+ this.firstEdge = e;
263
+ }
264
+ this.nextEdge = e + 1;
265
+ }
266
+ /**
267
+ * Pick up the reserved columns the builder wrote during its own expansion.
268
+ */
269
+ adoptExpansionColumns() {
270
+ this.directedHandle = this.sink.declareEdgeColumn(DIRECTED_DECL);
271
+ this.pairHandle = this.sink.declareEdgeColumn(PAIR_DECL);
272
+ }
273
+ /**
274
+ * Declare the reserved columns on first use in a directed sink and backfill graphty.directed
275
+ * = true for every edge this resolver pushed so far (they were directed in the source).
276
+ */
277
+ ensureExpansionColumns() {
278
+ if (this.pairHandle !== INVALID_INDEX) {
279
+ return;
280
+ }
281
+ this.directedHandle = this.sink.declareEdgeColumn(DIRECTED_DECL);
282
+ this.pairHandle = this.sink.declareEdgeColumn(PAIR_DECL);
283
+ if (this.firstEdge >= 0) {
284
+ for (let e = this.firstEdge; e < this.nextEdge; e++) {
285
+ this.sink.setEdgeValue(this.directedHandle, e, true);
286
+ }
287
+ }
288
+ }
289
+ /** Declare graphty.mutual on first use. */
290
+ ensureMutualColumn() {
291
+ if (this.mutualHandle === INVALID_INDEX) {
292
+ this.mutualHandle = this.sink.declareEdgeColumn(MUTUAL_DECL);
293
+ }
294
+ }
295
+ }
296
+ /**
297
+ * The reason of a refused setDirected(), for messages.
298
+ * @param err - the E_DIRECTED error
299
+ * @returns details.reason when it is a string, "refused" otherwise
300
+ */
301
+ function reasonOf(err) {
302
+ const { reason } = err.details;
303
+ return typeof reason === "string" ? reason : "refused";
304
+ }
305
+ /**
306
+ * The word for a direction, for messages.
307
+ * @param directed - the direction
308
+ * @returns "directed" or "undirected"
309
+ */
310
+ function direction(directed) {
311
+ return directed ? "directed" : "undirected";
312
+ }
313
+ /**
314
+ * Build the pair-folding view of a snapshot (one pass over the role columns).
315
+ * @param snapshot - the snapshot
316
+ * @param options - the per-format choice
317
+ * @returns the view
318
+ */
319
+ export function pairFolding(snapshot, options = {}) {
320
+ const foldMutual = options.foldMutual ?? false;
321
+ const directedColumn = roleColumn(snapshot.edges.byRole("directed"), "bool");
322
+ const pairColumn = roleColumn(snapshot.edges.byRole("pair"), "u32");
323
+ const mutualColumn = roleColumn(snapshot.edges.byRole("mutual"), "bool");
324
+ const { edgeCount } = snapshot;
325
+ const mateOf = (e) => {
326
+ if (pairColumn === null || !pairColumn.isSet(e)) {
327
+ return INVALID_INDEX;
328
+ }
329
+ const mate = pairColumn.value(e);
330
+ return typeof mate === "number" && mate !== INVALID_INDEX ? mate : INVALID_INDEX;
331
+ };
332
+ const sourceDirected = (e) => directedColumn === null || !directedColumn.isSet(e) || directedColumn.value(e) === true;
333
+ const isMutual = (e) => {
334
+ if (mutualColumn === null) {
335
+ return false;
336
+ }
337
+ if (mutualColumn.isSet(e) && mutualColumn.value(e) === true) {
338
+ return true;
339
+ }
340
+ const mate = mateOf(e);
341
+ return mate !== INVALID_INDEX && mutualColumn.isSet(mate) && mutualColumn.value(mate) === true;
342
+ };
343
+ const folded = (e) => {
344
+ const mate = mateOf(e);
345
+ if (mate === INVALID_INDEX || mate >= e) {
346
+ return false;
347
+ }
348
+ // an undirected pair always folds; a mutual pair (directed on both halves) folds on request
349
+ return !sourceDirected(e) || (foldMutual && isMutual(e));
350
+ };
351
+ let mutualCount = 0;
352
+ if (mutualColumn !== null) {
353
+ for (let e = 0; e < edgeCount; e++) {
354
+ if (mutualColumn.isSet(e) && mutualColumn.value(e) === true && mateOf(e) > e) {
355
+ mutualCount++;
356
+ }
357
+ }
358
+ }
359
+ return { expanded: pairColumn !== null, mutualCount, folded, mateOf, sourceDirected, isMutual };
360
+ }
361
+ /**
362
+ * A role column when it has the dtype the role requires, else null.
363
+ * @param column - the column, or null
364
+ * @param dtype - the required dtype
365
+ * @returns the column or null
366
+ */
367
+ function roleColumn(column, dtype) {
368
+ return column !== null && column.dtype === dtype ? column : null;
369
+ }
370
+ //# sourceMappingURL=direction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direction.js","sourceRoot":"","sources":["../../../src/common/direction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Id, label and value escaping for the text formats (design section 8.5), one function per
3
+ * syntax, with the inverse where the importer needs it: XML attribute and element text (GEXF,
4
+ * GraphML), GML quoted strings (`"` and `&` and non-ASCII as `&#NN;` character entities, the
5
+ * NetworkX convention), DOT ids (bare when the grammar allows, quoted with `\"` otherwise), RFC
6
+ * 4180 CSV cells and Pajek labels.
7
+ */
8
+ /**
9
+ * Escape text for an XML element body: `&`, `<`, `>` and a carriage return (which XML
10
+ * end-of-line handling would turn into a line feed on every read) as character references. A
11
+ * character XML 1.0 forbids (a C0 control other than tab / LF / CR, U+FFFE, U+FFFF, a lone
12
+ * surrogate) has no XML spelling at all and is E_COLUMN_TYPE; the exporters' check() counts them.
13
+ * @param text - the text
14
+ * @returns the escaped text
15
+ */
16
+ export declare function escapeXmlText(text: string): string;
17
+ /**
18
+ * Escape text for a double-quoted XML attribute value: `&`, `<`, `>`, `"` and the whitespace
19
+ * characters attribute normalisation would fold; a character XML 1.0 forbids is E_COLUMN_TYPE.
20
+ * @param text - the text
21
+ * @returns the escaped text
22
+ */
23
+ export declare function escapeXmlAttribute(text: string): string;
24
+ /**
25
+ * Quote a GML string value: double quotes around the text with `"`, `&` and every character
26
+ * outside printable ASCII written as `&#NN;` (NetworkX's writer convention, which its reader and
27
+ * Gephi's decode).
28
+ * A lone surrogate cannot be written and is E_COLUMN_TYPE.
29
+ * @param text - the text
30
+ * @returns the quoted GML string
31
+ */
32
+ export declare function quoteGmlString(text: string): string;
33
+ /**
34
+ * Decode the character entities of a GML string body (the inverse of quoteGmlString on the text
35
+ * between the quotes). An unknown entity is left as written.
36
+ * @param body - the text between the quotes
37
+ * @returns the decoded text
38
+ */
39
+ export declare function decodeGmlString(body: string): string;
40
+ /**
41
+ * Whether a text is a DOT ID that needs no quotes: an alphanumeric identifier not starting with
42
+ * a digit, or a numeral, and not a keyword (case-insensitive).
43
+ * @param text - the text
44
+ * @returns true when the text can be written bare
45
+ */
46
+ export declare function isBareDotId(text: string): boolean;
47
+ /**
48
+ * Whether a text can be written as a DOT ID at all. Graphviz's scanner consumes a backslash pair
49
+ * `\\` as one unit and `\"` as an escaped quote, left to right, so a backslash that precedes a
50
+ * double quote or ends the text cannot be written: the written `\\"` reads as a pair and a closing
51
+ * quote, and a trailing backslash escapes the closing quote. Every other text is writable;
52
+ * quoteDotId() writes it.
53
+ * @param text - the id, name or value text
54
+ * @returns true when quoteDotId(text) reads back as `text`
55
+ */
56
+ export declare function isWritableDotText(text: string): boolean;
57
+ /**
58
+ * Write a DOT ID: bare when the grammar allows, otherwise double-quoted with `"` escaped as `\"`.
59
+ * In DOT quoted strings the dyad `\"` is the only escape; every other character, a backslash and
60
+ * a raw line break included, is kept as written, so nothing else is rewritten. A text ending in a
61
+ * backslash has no DOT spelling (isWritableDotText); the caller refuses it before writing.
62
+ * @param text - the id or label text
63
+ * @returns the DOT ID
64
+ */
65
+ export declare function quoteDotId(text: string): string;
66
+ /**
67
+ * Write a set CSV cell per RFC 4180: quoted with `"` doubled when the text contains the
68
+ * delimiter, a quote, a CR or LF, or leading / trailing whitespace; bare otherwise. The empty
69
+ * string is written as the quoted empty cell `""`, so the importers can tell a set empty string
70
+ * (and an empty-string node id, legal under design section 4.1) from an unset cell, which every
71
+ * exporter writes as nothing between the delimiters.
72
+ * @param text - the cell text of a set cell
73
+ * @param delimiter - the field delimiter (default ",")
74
+ * @returns the cell as written
75
+ */
76
+ export declare function quoteCsvCell(text: string, delimiter?: string): string;
77
+ /**
78
+ * Whether a text can be a Pajek label: Pajek has no escape mechanism inside its double-quoted
79
+ * labels, so a text containing a double quote, a CR or an LF cannot be written.
80
+ * @param text - the label text
81
+ * @returns true when quotePajekLabel() can write it
82
+ */
83
+ export declare function isPajekLabel(text: string): boolean;
84
+ /**
85
+ * Write a Pajek label: bare when it is a single run of non-space, non-quote characters, otherwise
86
+ * double-quoted. E_UNSUPPORTED (reason "pajek label") for a text isPajekLabel() rejects; the
87
+ * exporter's check() counts those.
88
+ * @param text - the label text
89
+ * @returns the label as written
90
+ */
91
+ export declare function quotePajekLabel(text: string): string;
92
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../../src/common/escape.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD;AAgBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcnD;AAKD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUpD;AAKD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKjD;AAuBD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,MAAM,CAclE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWpD"}