@graphty/graph-io 0.3.19 → 0.3.21

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 (201) hide show
  1. package/README.md +49 -4
  2. package/dist/chunks/{escape-CWExcecC.js → escape-B-tkk_Cl.js} +74 -16
  3. package/dist/chunks/escape-B-tkk_Cl.js.map +1 -0
  4. package/dist/chunks/{writer-DQiKgQJc.js → export-Bh60Dv-n.js} +5 -79
  5. package/dist/chunks/export-Bh60Dv-n.js.map +1 -0
  6. package/dist/chunks/{exporter-CbMZyVt-.js → exporter-BGrsWamJ.js} +7 -6
  7. package/dist/chunks/{exporter-CbMZyVt-.js.map → exporter-BGrsWamJ.js.map} +1 -1
  8. package/dist/chunks/exporter-DIeGJXAZ.js +834 -0
  9. package/dist/chunks/exporter-DIeGJXAZ.js.map +1 -0
  10. package/dist/chunks/{importer-BNFuV1-K.js → importer-BWY2FFc5.js} +28 -7
  11. package/dist/chunks/importer-BWY2FFc5.js.map +1 -0
  12. package/dist/chunks/importer-DD-xv9_Y.js +1471 -0
  13. package/dist/chunks/importer-DD-xv9_Y.js.map +1 -0
  14. package/dist/chunks/{importer-BAP4PrxR.js → importer-DET1tg6s.js} +30 -20
  15. package/dist/chunks/importer-DET1tg6s.js.map +1 -0
  16. package/dist/chunks/{importer-ByPGO-09.js → importer-DEcKhsmQ.js} +2 -2
  17. package/dist/chunks/{importer-ByPGO-09.js.map → importer-DEcKhsmQ.js.map} +1 -1
  18. package/dist/chunks/{importer-BW-Ft2ps.js → importer-DIrbbnAf.js} +6 -5
  19. package/dist/chunks/{importer-BW-Ft2ps.js.map → importer-DIrbbnAf.js.map} +1 -1
  20. package/dist/chunks/importer-D_e7e7LX.js +3055 -0
  21. package/dist/chunks/importer-D_e7e7LX.js.map +1 -0
  22. package/dist/chunks/{importer-Bm1_5vPS.js → importer-eUREhBGj.js} +11 -8
  23. package/dist/chunks/importer-eUREhBGj.js.map +1 -0
  24. package/dist/chunks/{importer-DOepkgnG.js → importer-vi3bSdtw.js} +4 -4
  25. package/dist/chunks/{importer-DOepkgnG.js.map → importer-vi3bSdtw.js.map} +1 -1
  26. package/dist/chunks/{importer-BVGtU1NA.js → importer-zGLo8Dg_.js} +6 -5
  27. package/dist/chunks/{importer-BVGtU1NA.js.map → importer-zGLo8Dg_.js.map} +1 -1
  28. package/dist/chunks/{json-elements-CZY1wiZh.js → json-elements-DDS8N2Dd.js} +2 -2
  29. package/dist/chunks/{json-elements-CZY1wiZh.js.map → json-elements-DDS8N2Dd.js.map} +1 -1
  30. package/dist/chunks/{records-BzNicMsf.js → records-dbRkxwaq.js} +2 -2
  31. package/dist/chunks/{records-BzNicMsf.js.map → records-dbRkxwaq.js.map} +1 -1
  32. package/dist/chunks/{report-BcWboivV.js → report-B1z4WT9e.js} +143 -111
  33. package/dist/chunks/{report-BcWboivV.js.map → report-B1z4WT9e.js.map} +1 -1
  34. package/dist/chunks/{weights-CwISIpCP.js → weights-Dzba96G3.js} +5 -5
  35. package/dist/chunks/{weights-CwISIpCP.js.map → weights-Dzba96G3.js.map} +1 -1
  36. package/dist/chunks/writer-C7flM-Ih.js +77 -0
  37. package/dist/chunks/writer-C7flM-Ih.js.map +1 -0
  38. package/dist/csv.js +6 -5
  39. package/dist/csv.js.map +1 -1
  40. package/dist/cx.js +1 -1
  41. package/dist/cx2.js +2 -2
  42. package/dist/cys.d.ts +1 -0
  43. package/dist/cys.js +6 -0
  44. package/dist/cys.js.map +1 -0
  45. package/dist/dot.js +1 -1
  46. package/dist/gexf.js +5 -4
  47. package/dist/gexf.js.map +1 -1
  48. package/dist/gml.js +12 -14
  49. package/dist/gml.js.map +1 -1
  50. package/dist/graph-io.js +288 -141
  51. package/dist/graph-io.js.map +1 -1
  52. package/dist/graphml.js +1 -1
  53. package/dist/json.js +1 -1
  54. package/dist/neo4j.js +6 -5
  55. package/dist/neo4j.js.map +1 -1
  56. package/dist/obo.js +1 -1
  57. package/dist/pajek.js +1 -1
  58. package/dist/src/common/cell-budget.d.ts +84 -0
  59. package/dist/src/common/cell-budget.d.ts.map +1 -0
  60. package/dist/src/common/cell-budget.js +138 -0
  61. package/dist/src/common/cell-budget.js.map +1 -0
  62. package/dist/src/common/input.d.ts +10 -0
  63. package/dist/src/common/input.d.ts.map +1 -1
  64. package/dist/src/common/input.js +39 -0
  65. package/dist/src/common/input.js.map +1 -1
  66. package/dist/src/common/options.d.ts +6 -0
  67. package/dist/src/common/options.d.ts.map +1 -1
  68. package/dist/src/common/options.js +1 -1
  69. package/dist/src/common/options.js.map +1 -1
  70. package/dist/src/common/xml.d.ts +37 -3
  71. package/dist/src/common/xml.d.ts.map +1 -1
  72. package/dist/src/common/xml.js +86 -6
  73. package/dist/src/common/xml.js.map +1 -1
  74. package/dist/src/common/zip.d.ts +92 -0
  75. package/dist/src/common/zip.d.ts.map +1 -0
  76. package/dist/src/common/zip.js +399 -0
  77. package/dist/src/common/zip.js.map +1 -0
  78. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  79. package/dist/src/formats/cx/importer.js +26 -17
  80. package/dist/src/formats/cx/importer.js.map +1 -1
  81. package/dist/src/formats/cys/constants.d.ts +68 -0
  82. package/dist/src/formats/cys/constants.d.ts.map +1 -0
  83. package/dist/src/formats/cys/constants.js +76 -0
  84. package/dist/src/formats/cys/constants.js.map +1 -0
  85. package/dist/src/formats/cys/importer.d.ts +38 -0
  86. package/dist/src/formats/cys/importer.d.ts.map +1 -0
  87. package/dist/src/formats/cys/importer.js +830 -0
  88. package/dist/src/formats/cys/importer.js.map +1 -0
  89. package/dist/src/formats/cys/index.d.ts +7 -0
  90. package/dist/src/formats/cys/index.d.ts.map +1 -0
  91. package/dist/src/formats/cys/index.js +7 -0
  92. package/dist/src/formats/cys/index.js.map +1 -0
  93. package/dist/src/formats/cys/session.d.ts +132 -0
  94. package/dist/src/formats/cys/session.d.ts.map +1 -0
  95. package/dist/src/formats/cys/session.js +315 -0
  96. package/dist/src/formats/cys/session.js.map +1 -0
  97. package/dist/src/formats/cys/tables.d.ts +90 -0
  98. package/dist/src/formats/cys/tables.d.ts.map +1 -0
  99. package/dist/src/formats/cys/tables.js +293 -0
  100. package/dist/src/formats/cys/tables.js.map +1 -0
  101. package/dist/src/formats/dot/exporter.d.ts +2 -0
  102. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  103. package/dist/src/formats/dot/exporter.js +12 -0
  104. package/dist/src/formats/dot/exporter.js.map +1 -1
  105. package/dist/src/formats/dot/importer.js +6 -2
  106. package/dist/src/formats/dot/importer.js.map +1 -1
  107. package/dist/src/formats/gexf/importer.d.ts +2 -2
  108. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  109. package/dist/src/formats/gexf/importer.js +1 -1
  110. package/dist/src/formats/gexf/importer.js.map +1 -1
  111. package/dist/src/formats/gml/exporter.d.ts +0 -8
  112. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  113. package/dist/src/formats/gml/exporter.js +7 -17
  114. package/dist/src/formats/gml/exporter.js.map +1 -1
  115. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  116. package/dist/src/formats/json/exporter.js +3 -1
  117. package/dist/src/formats/json/exporter.js.map +1 -1
  118. package/dist/src/formats/json/importer.d.ts.map +1 -1
  119. package/dist/src/formats/json/importer.js +3 -2
  120. package/dist/src/formats/json/importer.js.map +1 -1
  121. package/dist/src/formats/xgmml/columns.d.ts +152 -0
  122. package/dist/src/formats/xgmml/columns.d.ts.map +1 -0
  123. package/dist/src/formats/xgmml/columns.js +593 -0
  124. package/dist/src/formats/xgmml/columns.js.map +1 -0
  125. package/dist/src/formats/xgmml/constants.d.ts +196 -0
  126. package/dist/src/formats/xgmml/constants.d.ts.map +1 -0
  127. package/dist/src/formats/xgmml/constants.js +197 -0
  128. package/dist/src/formats/xgmml/constants.js.map +1 -0
  129. package/dist/src/formats/xgmml/document.d.ts +361 -0
  130. package/dist/src/formats/xgmml/document.d.ts.map +1 -0
  131. package/dist/src/formats/xgmml/document.js +695 -0
  132. package/dist/src/formats/xgmml/document.js.map +1 -0
  133. package/dist/src/formats/xgmml/emit.d.ts +341 -0
  134. package/dist/src/formats/xgmml/emit.d.ts.map +1 -0
  135. package/dist/src/formats/xgmml/emit.js +1275 -0
  136. package/dist/src/formats/xgmml/emit.js.map +1 -0
  137. package/dist/src/formats/xgmml/exporter.d.ts +24 -0
  138. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -0
  139. package/dist/src/formats/xgmml/exporter.js +999 -0
  140. package/dist/src/formats/xgmml/exporter.js.map +1 -0
  141. package/dist/src/formats/xgmml/importer.d.ts +58 -0
  142. package/dist/src/formats/xgmml/importer.d.ts.map +1 -0
  143. package/dist/src/formats/xgmml/importer.js +360 -0
  144. package/dist/src/formats/xgmml/importer.js.map +1 -0
  145. package/dist/src/formats/xgmml/index.d.ts +8 -0
  146. package/dist/src/formats/xgmml/index.d.ts.map +1 -0
  147. package/dist/src/formats/xgmml/index.js +8 -0
  148. package/dist/src/formats/xgmml/index.js.map +1 -0
  149. package/dist/src/formats/xgmml/values.d.ts +60 -0
  150. package/dist/src/formats/xgmml/values.d.ts.map +1 -0
  151. package/dist/src/formats/xgmml/values.js +148 -0
  152. package/dist/src/formats/xgmml/values.js.map +1 -0
  153. package/dist/src/index.d.ts +2 -0
  154. package/dist/src/index.d.ts.map +1 -1
  155. package/dist/src/index.js +2 -0
  156. package/dist/src/index.js.map +1 -1
  157. package/dist/src/registry.d.ts +7 -0
  158. package/dist/src/registry.d.ts.map +1 -1
  159. package/dist/src/registry.js +25 -10
  160. package/dist/src/registry.js.map +1 -1
  161. package/dist/src/sniff.d.ts +1 -1
  162. package/dist/src/sniff.d.ts.map +1 -1
  163. package/dist/src/sniff.js +2 -0
  164. package/dist/src/sniff.js.map +1 -1
  165. package/dist/xgmml.d.ts +1 -0
  166. package/dist/xgmml.js +9 -0
  167. package/dist/xgmml.js.map +1 -0
  168. package/package.json +15 -2
  169. package/src/common/cell-budget.ts +170 -0
  170. package/src/common/input.ts +40 -0
  171. package/src/common/options.ts +1 -1
  172. package/src/common/xml.ts +127 -6
  173. package/src/common/zip.ts +472 -0
  174. package/src/formats/cx/importer.ts +27 -19
  175. package/src/formats/cys/constants.ts +99 -0
  176. package/src/formats/cys/importer.ts +1100 -0
  177. package/src/formats/cys/index.ts +7 -0
  178. package/src/formats/cys/session.ts +428 -0
  179. package/src/formats/cys/tables.ts +400 -0
  180. package/src/formats/dot/exporter.ts +17 -0
  181. package/src/formats/dot/importer.ts +6 -2
  182. package/src/formats/gexf/importer.ts +0 -1
  183. package/src/formats/gml/exporter.ts +7 -18
  184. package/src/formats/json/exporter.ts +3 -1
  185. package/src/formats/json/importer.ts +3 -2
  186. package/src/formats/xgmml/columns.ts +747 -0
  187. package/src/formats/xgmml/constants.ts +265 -0
  188. package/src/formats/xgmml/document.ts +975 -0
  189. package/src/formats/xgmml/emit.ts +1563 -0
  190. package/src/formats/xgmml/exporter.ts +1215 -0
  191. package/src/formats/xgmml/importer.ts +491 -0
  192. package/src/formats/xgmml/index.ts +8 -0
  193. package/src/formats/xgmml/values.ts +183 -0
  194. package/src/index.ts +9 -0
  195. package/src/registry.ts +41 -15
  196. package/src/sniff.ts +5 -1
  197. package/dist/chunks/escape-CWExcecC.js.map +0 -1
  198. package/dist/chunks/importer-BAP4PrxR.js.map +0 -1
  199. package/dist/chunks/importer-BNFuV1-K.js.map +0 -1
  200. package/dist/chunks/importer-Bm1_5vPS.js.map +0 -1
  201. package/dist/chunks/writer-DQiKgQJc.js.map +0 -1
@@ -0,0 +1,834 @@
1
+ import { GraphFormatError } from "@graphty/graph-format";
2
+ import { c as childrenCsr } from "./children-CL3Cy0ez.js";
3
+ import { V as resolveExportOptions, X as pairFolding, _ as DictHeuristic } from "./report-B1z4WT9e.js";
4
+ import { e as escapeXmlAttribute, x as xmlIllegalTextNotes, a as escapeXmlText } from "./escape-B-tkk_Cl.js";
5
+ import { c as capabilities, a as checkCapabilities, L as LOSS } from "./export-Bh60Dv-n.js";
6
+ import { e as explicitWeights, f as formatF32, a as formatF64 } from "./weights-Dzba96G3.js";
7
+ import { j as joinText, e as encodeChunks } from "./writer-C7flM-Ih.js";
8
+ import { F as FORMAT, M as META_KEY, b as XLINK_NAMESPACE, C as CY_NAMESPACE, c as XGMML_NAMESPACE, a as XGMML_LOSS, Z as Z_COLUMN, L as LABEL_COLUMN, I as INTERACTION_COLUMN, d as aliasesOf, G as GRAPHICS_COLUMN, S as SUBGRAPH_COLUMN, N as NESTED_NETWORK_COLUMN, e as NETWORK_POINTER_COLUMN, f as NETWORKS_COLUMN, E as EDGE_ID_COLUMN, P as POSITION_COLUMN, g as PARENT_COLUMN, h as PARENTS_COLUMN, i as XGMML_ORIGIN_NAMESPACE, j as CYTOSCAPE_ORIGIN_NAMESPACE } from "./importer-D_e7e7LX.js";
9
+ const CAPABILITIES = capabilities({
10
+ mixedDirection: true,
11
+ multiEdges: true,
12
+ selfLoops: true,
13
+ edgeIds: "optional",
14
+ idCharset: "any",
15
+ dtypes: ["string", "dict", "f64", "f32", "i32", "u32", "u8", "bool", "list"],
16
+ components: false,
17
+ lists: true,
18
+ json: false,
19
+ defaults: false,
20
+ options: false,
21
+ hierarchy: true,
22
+ temporal: "none",
23
+ graphAttributes: true,
24
+ positions: true,
25
+ viz: false
26
+ });
27
+ const SLOT_ROLES = /* @__PURE__ */ new Set(["label", "id", "parent", "parents", "position"]);
28
+ const ROLE_NAMES = Object.freeze({
29
+ label: LABEL_COLUMN,
30
+ id: EDGE_ID_COLUMN,
31
+ parent: PARENT_COLUMN,
32
+ position: POSITION_COLUMN
33
+ });
34
+ const DROPPED_ROLES = /* @__PURE__ */ new Set([
35
+ "color",
36
+ "size",
37
+ "shape",
38
+ "thickness",
39
+ "start",
40
+ "end",
41
+ "timestamp",
42
+ "timestamps",
43
+ "spells",
44
+ "open",
45
+ "spellsOpen"
46
+ ]);
47
+ const READ_ATTRIBUTES = {
48
+ node: /* @__PURE__ */ new Set(["id", "label", "name"]),
49
+ edge: /* @__PURE__ */ new Set(["id", "label", "name", "source", "target", "weight"])
50
+ };
51
+ const STRUCTURAL_ROLES = /* @__PURE__ */ new Set([
52
+ "directed",
53
+ "pair",
54
+ "mutual",
55
+ "weight",
56
+ "parent",
57
+ "parents",
58
+ "position"
59
+ ]);
60
+ const RESERVED_NODE_NAMES = /* @__PURE__ */ new Set([
61
+ LABEL_COLUMN,
62
+ POSITION_COLUMN,
63
+ Z_COLUMN,
64
+ GRAPHICS_COLUMN,
65
+ PARENT_COLUMN,
66
+ PARENTS_COLUMN,
67
+ SUBGRAPH_COLUMN,
68
+ NESTED_NETWORK_COLUMN,
69
+ NETWORK_POINTER_COLUMN,
70
+ NETWORKS_COLUMN
71
+ ]);
72
+ const RESERVED_EDGE_NAMES = /* @__PURE__ */ new Set([EDGE_ID_COLUMN, LABEL_COLUMN, GRAPHICS_COLUMN]);
73
+ const RESERVED_NAMES = {
74
+ graph: /* @__PURE__ */ new Set([GRAPHICS_COLUMN]),
75
+ node: RESERVED_NODE_NAMES,
76
+ edge: RESERVED_EDGE_NAMES
77
+ };
78
+ const GRAPHICS_ATTRIBUTES = /* @__PURE__ */ new Set([
79
+ "type",
80
+ "w",
81
+ "h",
82
+ "d",
83
+ "image",
84
+ "bitmap",
85
+ "width",
86
+ "arrow",
87
+ "capstyle",
88
+ "joinstyle",
89
+ "smooth",
90
+ "splinesteps",
91
+ "justify",
92
+ "font",
93
+ "background",
94
+ "foreground",
95
+ "extent",
96
+ "start",
97
+ "style",
98
+ "stipple",
99
+ "visible",
100
+ "fill",
101
+ "outline",
102
+ "anchor"
103
+ ]);
104
+ const I32_MAX = 2147483647;
105
+ function typesOf(column, dtype) {
106
+ if (column.meta.components > 1) {
107
+ return ["string", "String"];
108
+ }
109
+ switch (dtype) {
110
+ case "bool":
111
+ return ["boolean", "Boolean"];
112
+ case "i32":
113
+ case "u8":
114
+ return ["integer", "Integer"];
115
+ case "u32":
116
+ return maxValue(column) > I32_MAX ? ["integer", "Long"] : ["integer", "Integer"];
117
+ case "f32":
118
+ case "f64":
119
+ return column.meta.origin?.type === "long" && allSafeIntegers(column) ? ["integer", "Long"] : ["real", "Double"];
120
+ default:
121
+ return ["string", "String"];
122
+ }
123
+ }
124
+ function allSafeIntegers(column) {
125
+ for (let r = 0; r < column.length; r++) {
126
+ if (!column.isSet(r)) {
127
+ continue;
128
+ }
129
+ const items = column.dtype === "list" ? [...column.sliceOf(r)] : [column.value(r)];
130
+ if (!items.every((item) => typeof item === "number" && Number.isSafeInteger(item))) {
131
+ return false;
132
+ }
133
+ }
134
+ return true;
135
+ }
136
+ function maxValue(column) {
137
+ let max = 0;
138
+ for (let r = 0; r < column.length; r++) {
139
+ if (!column.isSet(r)) {
140
+ continue;
141
+ }
142
+ const value = column.value(r);
143
+ const items = column.dtype === "list" ? [...column.sliceOf(r)] : [value];
144
+ for (const item of items) {
145
+ if (typeof item === "number" && item > max) {
146
+ max = item;
147
+ }
148
+ }
149
+ }
150
+ return max;
151
+ }
152
+ function owned(column, namespace) {
153
+ const { origin } = column.meta;
154
+ return origin !== null && origin.namespace === namespace;
155
+ }
156
+ function planTable(table, domain, snapshot, note) {
157
+ const writes = [];
158
+ const reserved = RESERVED_NAMES[domain];
159
+ const hasLabelRole = domain !== "graph" && (domain === "node" ? snapshot.nodes : snapshot.edges).byRole("label") !== null;
160
+ for (const column of table) {
161
+ const { meta } = column;
162
+ if (meta.role !== null && (STRUCTURAL_ROLES.has(meta.role) || DROPPED_ROLES.has(meta.role) || meta.role === "id" || meta.role === "timeText")) {
163
+ continue;
164
+ }
165
+ const kind = slotOf(column, domain, hasLabelRole);
166
+ const set = column.length - column.nullCount;
167
+ if (kind === "att" && reserved.has(meta.name)) {
168
+ note(
169
+ LOSS.COLUMN_NAME_CHANGED,
170
+ `${domain} column "${meta.name}" is named like a column the XGMML importer owns and reads back renamed`,
171
+ meta.name,
172
+ set
173
+ );
174
+ } else if (kind === "label" && meta.dtype !== "string" && meta.dtype !== "dict") {
175
+ note(
176
+ LOSS.DTYPE,
177
+ `${domain} label column "${meta.name}" (${meta.dtype}) is written as text and reads back as string`,
178
+ meta.name,
179
+ set
180
+ );
181
+ } else if (kind === "label" && meta.role === null) {
182
+ note(
183
+ LOSS.ROLE_ASSUMED,
184
+ `${domain} column "${meta.name}" is written as the label and reads back with the label role`,
185
+ meta.name,
186
+ set
187
+ );
188
+ }
189
+ if (kind === "att") {
190
+ attNotes(column, domain, note);
191
+ }
192
+ const item = meta.dtype === "list" ? meta.itemDtype : meta.dtype;
193
+ const [type, cyType] = meta.dtype === "list" ? ["list", "List"] : declaredTypes(column, typesOf(column, item));
194
+ writes.push({
195
+ column,
196
+ name: meta.name,
197
+ kind,
198
+ type,
199
+ cyType,
200
+ elementType: meta.dtype === "list" ? typesOf(column, item)[1] : null
201
+ });
202
+ }
203
+ return writes;
204
+ }
205
+ function slotOf(column, domain, hasLabelRole) {
206
+ const { meta } = column;
207
+ if (domain !== "graph" && untypedAttribute(column, domain)) {
208
+ return "xml";
209
+ }
210
+ if (meta.role === "label" || !hasLabelRole && domain !== "graph" && meta.role === null && meta.name === LABEL_COLUMN && (meta.dtype === "string" || meta.dtype === "dict")) {
211
+ return "label";
212
+ }
213
+ if (meta.dtype === "json" && meta.name === GRAPHICS_COLUMN && owned(column, XGMML_ORIGIN_NAMESPACE)) {
214
+ return "graphics";
215
+ }
216
+ if (domain !== "node") {
217
+ return "att";
218
+ }
219
+ if (meta.name === Z_COLUMN && meta.dtype === "f64" && meta.role === null) {
220
+ return "z";
221
+ }
222
+ if (meta.name === SUBGRAPH_COLUMN && meta.dtype === "json" && owned(column, XGMML_ORIGIN_NAMESPACE)) {
223
+ return "subgraph";
224
+ }
225
+ if (meta.name === NESTED_NETWORK_COLUMN && meta.dtype === "string" && owned(column, CYTOSCAPE_ORIGIN_NAMESPACE)) {
226
+ return "nested";
227
+ }
228
+ if (meta.name === NETWORK_POINTER_COLUMN && meta.dtype === "string" && owned(column, XGMML_ORIGIN_NAMESPACE)) {
229
+ return "pointer";
230
+ }
231
+ if (meta.name === NETWORKS_COLUMN && meta.dtype === "list" && owned(column, XGMML_ORIGIN_NAMESPACE)) {
232
+ return "networks";
233
+ }
234
+ return "att";
235
+ }
236
+ function untypedAttribute(column, domain) {
237
+ const { meta } = column;
238
+ const { origin } = meta;
239
+ return origin !== null && origin.format === FORMAT && origin.type === null && origin.namespace === null && meta.role === null && meta.components === 1 && (meta.dtype === "string" || meta.dtype === "bool" || meta.dtype === "i32" || meta.dtype === "f64") && /^[A-Za-z_][A-Za-z0-9_.-]*$/.test(meta.name) && !READ_ATTRIBUTES[domain].has(meta.name);
240
+ }
241
+ function declaredTypes(column, types) {
242
+ const { origin } = column.meta;
243
+ if (origin !== null && origin.format === FORMAT && origin.type === types[0] && column.meta.components === 1) {
244
+ return [types[0], null];
245
+ }
246
+ return types;
247
+ }
248
+ function attNotes(column, domain, note) {
249
+ const { meta } = column;
250
+ const set = column.length - column.nullCount;
251
+ const label = `${domain} column "${meta.name}"`;
252
+ const item = meta.dtype === "list" ? meta.itemDtype : meta.dtype;
253
+ if (meta.dtype === "json") {
254
+ note(
255
+ XGMML_LOSS.JSON_AS_STRING,
256
+ `${label} holds nested values; they are written as JSON text and read back as strings`,
257
+ meta.name,
258
+ set
259
+ );
260
+ return;
261
+ }
262
+ if (item === "f32" || item === "u8" || item === "u32") {
263
+ note(
264
+ XGMML_LOSS.WIDENED_TYPE,
265
+ `${label} (${item}) is written as a wider Cytoscape type and reads back as ${readBackDtype(column, item)}`,
266
+ meta.name,
267
+ set
268
+ );
269
+ }
270
+ if (item === "string" || item === "dict") {
271
+ let escapes = 0;
272
+ for (let r = 0; r < column.length; r++) {
273
+ if (column.isSet(r)) {
274
+ const values = column.dtype === "list" ? [...column.sliceOf(r)] : [column.value(r)];
275
+ if (values.some((v) => typeof v === "string" && /\\[nt]/.test(v))) {
276
+ escapes++;
277
+ }
278
+ }
279
+ }
280
+ if (escapes > 0) {
281
+ note(
282
+ XGMML_LOSS.BACKSLASH_ESCAPE,
283
+ `${label}: ${escapes} value(s) hold a literal \\n or \\t, which Cytoscape's escape convention reads back as a newline or tab`,
284
+ meta.name,
285
+ escapes
286
+ );
287
+ }
288
+ }
289
+ if (meta.dtype === "string" || meta.dtype === "dict") {
290
+ const heuristic = new DictHeuristic();
291
+ for (let r = 0; r < column.length && !heuristic.decided; r++) {
292
+ if (column.isSet(r)) {
293
+ heuristic.observe(column.value(r));
294
+ }
295
+ }
296
+ const readsAs = heuristic.decide();
297
+ if (readsAs !== meta.dtype) {
298
+ note(
299
+ XGMML_LOSS.STORAGE_CLASS_CHANGED,
300
+ `${label} reads back as ${readsAs} (the cardinality heuristic)`,
301
+ meta.name,
302
+ null
303
+ );
304
+ }
305
+ }
306
+ }
307
+ function readBackDtype(column, item) {
308
+ if (item === "u8" || item === "u32" && maxValue(column) <= I32_MAX) {
309
+ return "i32";
310
+ }
311
+ return "f64";
312
+ }
313
+ function planExport(snapshot, options, escapes) {
314
+ const notes = checkCapabilities(snapshot, CAPABILITIES, options, {
315
+ roles: SLOT_ROLES,
316
+ roleNames: ROLE_NAMES,
317
+ positionDtype: "f32"
318
+ }).filter((n) => n.code !== LOSS.JSON);
319
+ const note = (code, message, column = null, count = null) => {
320
+ notes.push(Object.freeze({ code, message, column, count }));
321
+ };
322
+ notes.push(...xmlIllegalTextNotes(snapshot));
323
+ const folding = pairFolding(snapshot);
324
+ if (folding.mutualCount > 0) {
325
+ note(
326
+ XGMML_LOSS.MUTUAL_EXPANDED,
327
+ `${folding.mutualCount} mutual pair(s) are written as two directed edges; the mutual mark is lost`,
328
+ null,
329
+ folding.mutualCount
330
+ );
331
+ }
332
+ const numericIds = countNumericIds(snapshot);
333
+ if (numericIds > 0) {
334
+ note(
335
+ XGMML_LOSS.ID_TEXT_TYPE,
336
+ `${numericIds} numeric node id(s) are written as text and read back as strings`,
337
+ null,
338
+ numericIds
339
+ );
340
+ }
341
+ const edgeId = snapshot.edges.byRole("id");
342
+ if (edgeId !== null && edgeId.dtype !== "string" && edgeId.dtype !== "dict") {
343
+ note(
344
+ XGMML_LOSS.EDGE_ID_TEXT,
345
+ `edge id column "${edgeId.meta.name}" (${edgeId.dtype}) is written as text and reads back as strings`,
346
+ edgeId.meta.name,
347
+ null
348
+ );
349
+ }
350
+ const hierarchy = childrenCsr(snapshot);
351
+ if (hierarchy.unreachable > 0) {
352
+ note(
353
+ XGMML_LOSS.PARENT_CYCLE,
354
+ `${hierarchy.unreachable} node(s) whose parent chain never reaches a root are written at the top level and lose their parent`,
355
+ null,
356
+ hierarchy.unreachable
357
+ );
358
+ }
359
+ const parents = snapshot.nodes.byRole("parents");
360
+ if (parents !== null && snapshot.nodes.byRole("parent") !== null) {
361
+ note(
362
+ XGMML_LOSS.PARENTS_DROPPED,
363
+ `parents column "${parents.meta.name}" is not written: the "parent" column is the containment written`,
364
+ parents.meta.name,
365
+ parents.length - parents.nullCount
366
+ );
367
+ } else if (parents !== null && !multiParent(parents)) {
368
+ note(
369
+ LOSS.COLUMN_NAME_CHANGED,
370
+ `parents column "${parents.meta.name}" holds one parent per node and reads back as the "parent" column`,
371
+ parents.meta.name,
372
+ null
373
+ );
374
+ }
375
+ const position = snapshot.nodes.byRole("position");
376
+ if (position !== null) {
377
+ positionNotes(position, snapshot, note);
378
+ }
379
+ interactionNote(snapshot, note);
380
+ const weights = explicitWeights(snapshot);
381
+ for (const column of snapshot.edges) {
382
+ if (column.meta.name === "weight" && column.meta.role === null && !weights.weighted) {
383
+ note(LOSS.WEIGHT_KEY_CLASH, `edge column "weight" reads back as THE weight`, "weight", null);
384
+ }
385
+ }
386
+ return {
387
+ options,
388
+ escapes,
389
+ notes,
390
+ graph: planTable(snapshot.graph, "graph", snapshot, note),
391
+ nodes: planTable(snapshot.nodes, "node", snapshot, note),
392
+ edges: planTable(snapshot.edges, "edge", snapshot, note),
393
+ folding,
394
+ weights,
395
+ hierarchy,
396
+ reachable: reachableNodes(snapshot.nodeCount, hierarchy),
397
+ position,
398
+ edgeId
399
+ };
400
+ }
401
+ function interactionNote(snapshot, note) {
402
+ const label = snapshot.edges.byRole("label") ?? snapshot.edges.get(LABEL_COLUMN);
403
+ if (label === null || snapshot.edges.get(INTERACTION_COLUMN) !== null) {
404
+ return;
405
+ }
406
+ let shaped = 0;
407
+ for (let e = 0; e < label.length; e++) {
408
+ if (label.isSet(e) && aliasesOf(scalarText(label.value(e))) !== null) {
409
+ shaped++;
410
+ }
411
+ }
412
+ if (shaped > 0) {
413
+ note(
414
+ XGMML_LOSS.INTERACTION_FROM_LABEL,
415
+ `${shaped} edge label(s) have Cytoscape's "a (i) b" shape and read back with an "${INTERACTION_COLUMN}" column`,
416
+ INTERACTION_COLUMN,
417
+ shaped
418
+ );
419
+ }
420
+ }
421
+ function reachableNodes(nodeCount, hierarchy) {
422
+ const reached = new Uint8Array(nodeCount);
423
+ const stack = Array.from(hierarchy.roots);
424
+ for (const root of stack) {
425
+ reached[root] = 1;
426
+ }
427
+ while (stack.length > 0) {
428
+ for (const child of hierarchy.childrenOf(stack.pop())) {
429
+ if (reached[child] === 0) {
430
+ reached[child] = 1;
431
+ stack.push(child);
432
+ }
433
+ }
434
+ }
435
+ return reached;
436
+ }
437
+ function multiParent(column) {
438
+ for (let r = 0; r < column.length; r++) {
439
+ if (column.isSet(r) && column.dtype === "list" && column.sliceOf(r).length > 1) {
440
+ return true;
441
+ }
442
+ }
443
+ return false;
444
+ }
445
+ function positionNotes(position, snapshot, note) {
446
+ const { meta } = position;
447
+ if (meta.components !== 3) {
448
+ note(
449
+ XGMML_LOSS.POSITION,
450
+ `position column "${meta.name}" has ${meta.components} component(s) and reads back with 3`,
451
+ meta.name,
452
+ null
453
+ );
454
+ }
455
+ let nonFinite = 0;
456
+ let depth = 0;
457
+ for (let r = 0; r < position.length; r++) {
458
+ if (!position.isSet(r)) {
459
+ continue;
460
+ }
461
+ const xyz = Array.from(position.value(r));
462
+ if (xyz.slice(0, 2).some((v) => !Number.isFinite(v))) {
463
+ nonFinite++;
464
+ } else if ((xyz[2] ?? 0) !== 0) {
465
+ depth++;
466
+ }
467
+ }
468
+ if (nonFinite > 0) {
469
+ note(
470
+ XGMML_LOSS.POSITION,
471
+ `${nonFinite} position(s) with a non-finite coordinate are not written`,
472
+ meta.name,
473
+ nonFinite
474
+ );
475
+ }
476
+ const zColumn = snapshot.nodes.get(Z_COLUMN);
477
+ if (depth > 0) {
478
+ note(
479
+ XGMML_LOSS.POSITION,
480
+ zColumn === null ? `${depth} position(s) have a z; it is written as graphics z and reads back in the z column (zAs: "position" reads it as a coordinate)` : `${depth} position(s) have a z, but graphics z holds the z column; the position z is lost`,
481
+ meta.name,
482
+ depth
483
+ );
484
+ }
485
+ }
486
+ function countNumericIds(snapshot) {
487
+ let n = 0;
488
+ for (let i = 0; i < snapshot.nodeCount; i++) {
489
+ if (typeof snapshot.ids.idOf(i) === "number") {
490
+ n++;
491
+ }
492
+ }
493
+ return n;
494
+ }
495
+ function valueText(value, dtype, escapes) {
496
+ let text;
497
+ if (typeof value === "boolean") {
498
+ text = value ? "1" : "0";
499
+ } else if (typeof value === "number") {
500
+ text = dtype === "f32" ? formatF32(value) : formatF64(value);
501
+ } else if (typeof value === "string") {
502
+ text = escapes ? value.replace(/\n/g, "\\n").replace(/\t/g, "\\t") : value;
503
+ } else if (ArrayBuffer.isView(value)) {
504
+ text = JSON.stringify(Array.from(value));
505
+ } else {
506
+ text = JSON.stringify(value) ?? "";
507
+ }
508
+ return escapeXmlAttribute(text);
509
+ }
510
+ function scalarText(value) {
511
+ if (typeof value === "string") {
512
+ return value;
513
+ }
514
+ if (typeof value === "number") {
515
+ return formatF64(value);
516
+ }
517
+ if (typeof value === "boolean") {
518
+ return value ? "true" : "false";
519
+ }
520
+ return JSON.stringify(value) ?? "";
521
+ }
522
+ function idText(id) {
523
+ return typeof id === "number" ? formatF64(id) : id;
524
+ }
525
+ function xmlAttributesOf(writes, row) {
526
+ let out = "";
527
+ for (const w of writes) {
528
+ if (w.kind === "xml" && w.column.isSet(row)) {
529
+ out += ` ${w.name}="${escapeXmlAttribute(scalarText(w.column.value(row)))}"`;
530
+ }
531
+ }
532
+ return out;
533
+ }
534
+ function* attsOf(writes, row, first, plan, indent) {
535
+ for (const w of writes) {
536
+ if (w.kind !== "att") {
537
+ continue;
538
+ }
539
+ const { column } = w;
540
+ const isSet = column.isSet(row);
541
+ if (!isSet && !(first && column.nullCount === column.length)) {
542
+ continue;
543
+ }
544
+ const name = `${indent}<att name="${escapeXmlAttribute(w.name)}"`;
545
+ const types = `${w.type === null ? "" : ` type="${w.type}"`}${w.cyType === null ? "" : ` cy:type="${w.cyType}"`}`;
546
+ const extra = `${column.meta.extra.hidden === true ? ' cy:hidden="1"' : ""}${column.meta.extra.equation === true ? ' cy:equation="1"' : ""}`;
547
+ if (!isSet) {
548
+ yield `${name}${types}${w.elementType === null ? "" : ` cy:elementType="${w.elementType}"`}${extra}/>
549
+ `;
550
+ continue;
551
+ }
552
+ if (column.dtype === "list") {
553
+ const items = [...column.sliceOf(row)];
554
+ const [itemType, itemCy] = typesOf(column, column.meta.itemDtype);
555
+ yield `${name}${types} cy:elementType="${w.elementType ?? "String"}"${extra}${items.length === 0 ? "/>" : ">"}
556
+ `;
557
+ if (items.length > 0) {
558
+ for (const item of items) {
559
+ yield `${indent} <att name="${escapeXmlAttribute(w.name)}" value="${valueText(item, column.meta.itemDtype, plan.escapes)}" type="${itemType}" cy:type="${itemCy}"/>
560
+ `;
561
+ }
562
+ yield `${indent}</att>
563
+ `;
564
+ }
565
+ continue;
566
+ }
567
+ yield `${name} value="${valueText(column.value(row), column.dtype, plan.escapes)}"${types}${extra}/>
568
+ `;
569
+ }
570
+ }
571
+ function* graphicsOf(record, coords, indent) {
572
+ const attrs = [...coords];
573
+ const nested = [];
574
+ for (const [key, value] of Object.entries(record ?? {})) {
575
+ if (key === "Line") {
576
+ nested.push([key, value]);
577
+ } else if (typeof value === "string" && (GRAPHICS_ATTRIBUTES.has(key) || key.startsWith("cy:"))) {
578
+ attrs.push([key, value]);
579
+ } else {
580
+ nested.push([key, value]);
581
+ }
582
+ }
583
+ if (attrs.length === 0 && nested.length === 0) {
584
+ return;
585
+ }
586
+ const head = `${indent}<graphics${attrs.map(([k, v]) => ` ${k}="${escapeXmlAttribute(v)}"`).join("")}`;
587
+ if (nested.length === 0) {
588
+ yield `${head}/>
589
+ `;
590
+ return;
591
+ }
592
+ yield `${head}>
593
+ `;
594
+ for (const [key, value] of nested) {
595
+ if (key === "Line" && Array.isArray(value)) {
596
+ yield `${indent} <Line>
597
+ `;
598
+ for (const point of value) {
599
+ const entries = typeof point === "object" && point !== null ? Object.entries(point) : [];
600
+ yield `${indent} <point${entries.map(([k, v]) => ` ${k}="${escapeXmlAttribute(String(v))}"`).join("")}/>
601
+ `;
602
+ }
603
+ yield `${indent} </Line>
604
+ `;
605
+ } else {
606
+ yield* jsonAtt(key, value, `${indent} `);
607
+ }
608
+ }
609
+ yield `${indent}</graphics>
610
+ `;
611
+ }
612
+ function* jsonAtt(name, value, indent) {
613
+ const nameAttr = name === null ? "" : ` name="${escapeXmlAttribute(name)}"`;
614
+ if (Array.isArray(value)) {
615
+ yield `${indent}<att${nameAttr} type="list">
616
+ `;
617
+ for (const item of value) {
618
+ yield* jsonAtt(name, item, `${indent} `);
619
+ }
620
+ yield `${indent}</att>
621
+ `;
622
+ } else if (typeof value === "object" && value !== null) {
623
+ const entries = Object.entries(value);
624
+ if (name !== null && entries.every(([, v]) => typeof v === "string") && entries.length <= 3 && entries.every(([k]) => /^[a-z]$/.test(k))) {
625
+ yield `${indent}<att${nameAttr}${entries.map(([k, v]) => ` ${k}="${escapeXmlAttribute(v)}"`).join("")}/>
626
+ `;
627
+ return;
628
+ }
629
+ yield `${indent}<att${nameAttr}>
630
+ `;
631
+ for (const [key, item] of entries) {
632
+ yield* jsonAtt(key, item, `${indent} `);
633
+ }
634
+ yield `${indent}</att>
635
+ `;
636
+ } else if (value === null || value === void 0) {
637
+ yield `${indent}<att${nameAttr} type="string"/>
638
+ `;
639
+ } else {
640
+ yield `${indent}<att${nameAttr} value="${escapeXmlAttribute(scalarText(value))}" type="string"/>
641
+ `;
642
+ }
643
+ }
644
+ function slot(writes, kind) {
645
+ return writes.find((w) => w.kind === kind)?.column ?? null;
646
+ }
647
+ function cellOf(column, row) {
648
+ return column !== null && column.isSet(row) ? column.value(row) : null;
649
+ }
650
+ function coordsOf(plan, zColumn, node) {
651
+ const out = [];
652
+ const xyz = cellOf(plan.position, node);
653
+ if (xyz !== null) {
654
+ const [x, y, z2] = Array.from(xyz);
655
+ if (Number.isFinite(x) && Number.isFinite(y)) {
656
+ out.push(["x", formatF32(x)], ["y", formatF32(y === 0 ? 0 : -y)]);
657
+ if (zColumn === null && z2 !== void 0 && z2 !== 0 && Number.isFinite(z2)) {
658
+ out.push(["z", formatF32(z2)]);
659
+ }
660
+ }
661
+ }
662
+ const z = cellOf(zColumn, node);
663
+ if (typeof z === "number") {
664
+ out.push(["z", formatF64(z)]);
665
+ }
666
+ return out;
667
+ }
668
+ function* nodeOf(snapshot, plan, node, indent) {
669
+ const labelCol = slot(plan.nodes, "label");
670
+ const label = cellOf(labelCol, node);
671
+ yield `${indent}<node id="${escapeXmlAttribute(idText(snapshot.ids.idOf(node)))}"${label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`}${xmlAttributesOf(plan.nodes, node)}>
672
+ `;
673
+ const inner = `${indent} `;
674
+ yield* attsOf(plan.nodes, node, node === 0, plan, inner);
675
+ const children = plan.reachable[node] === 1 ? plan.hierarchy.childrenOf(node) : [];
676
+ const nested = cellOf(slot(plan.nodes, "nested"), node);
677
+ const pointer = cellOf(slot(plan.nodes, "pointer"), node);
678
+ const subgraph = cellOf(slot(plan.nodes, "subgraph"), node);
679
+ if (children.length > 0 || subgraph !== null) {
680
+ const sub = subgraph ?? {};
681
+ yield `${inner}<att name="__isGroup" value="1" type="boolean" cy:type="Boolean" cy:hidden="1"/>
682
+ `;
683
+ const id = typeof sub.id === "string" ? ` id="${escapeXmlAttribute(sub.id)}"` : "";
684
+ const lbl = typeof sub.label === "string" ? ` label="${escapeXmlAttribute(sub.label)}"` : "";
685
+ yield `${inner}<att>
686
+ ${inner} <graph${id}${lbl}>
687
+ `;
688
+ const atts = typeof sub.atts === "object" && sub.atts !== null ? Object.entries(sub.atts) : [];
689
+ for (const [key, value] of atts) {
690
+ yield* jsonAtt(key, value, `${inner} `);
691
+ }
692
+ for (const child of children) {
693
+ yield `${inner} <node xlink:href="#${escapeXmlAttribute(idText(snapshot.ids.idOf(child)))}"/>
694
+ `;
695
+ }
696
+ yield `${inner} </graph>
697
+ ${inner}</att>
698
+ `;
699
+ } else if (typeof nested === "string") {
700
+ yield `${inner}<att>
701
+ ${inner} <graph label="${escapeXmlAttribute(nested)}"/>
702
+ ${inner}</att>
703
+ `;
704
+ } else if (typeof pointer === "string") {
705
+ yield `${inner}<att>
706
+ ${inner} <graph xlink:href="${escapeXmlAttribute(pointer)}"/>
707
+ ${inner}</att>
708
+ `;
709
+ }
710
+ const graphics = cellOf(slot(plan.nodes, "graphics"), node);
711
+ yield* graphicsOf(graphics, coordsOf(plan, slot(plan.nodes, "z"), node), inner);
712
+ yield `${indent}</node>
713
+ `;
714
+ }
715
+ function* write(snapshot, options) {
716
+ const plan = planFor(snapshot, options);
717
+ const meta = snapshot.meta.extra[META_KEY];
718
+ const graphId = typeof meta?.graphId === "string" ? ` id="${escapeXmlAttribute(meta.graphId)}"` : "";
719
+ const keep = (meta?.directed === "0" || meta?.directed === "1") && snapshot.edgeCount > 0 && snapshot.edges.byRole("directed") === null;
720
+ let directed = snapshot.directed ? "1" : "0";
721
+ if (keep) {
722
+ directed = meta?.directed;
723
+ }
724
+ const name = snapshot.meta.name === null ? "" : ` label="${escapeXmlAttribute(snapshot.meta.name)}"`;
725
+ yield '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
726
+ yield `<graph${graphId}${name} directed="${directed}" cy:documentVersion="3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="${XLINK_NAMESPACE}" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cy="${CY_NAMESPACE}" xmlns="${XGMML_NAMESPACE}">
727
+ `;
728
+ yield* metadataOf(snapshot);
729
+ yield* attsOf(plan.graph, 0, true, plan, " ");
730
+ yield* graphicsOf(cellOf(slot(plan.graph, "graphics"), 0), [], " ");
731
+ for (let u = 0; u < snapshot.nodeCount; u++) {
732
+ yield* nodeOf(snapshot, plan, u, " ");
733
+ }
734
+ yield* networksOf(snapshot, plan);
735
+ yield* edgesOf(snapshot, plan);
736
+ yield "</graph>\n";
737
+ }
738
+ function* metadataOf(snapshot) {
739
+ const { name, description, created } = snapshot.meta;
740
+ if (description === null && created === null) {
741
+ return;
742
+ }
743
+ yield ' <att name="networkMetadata">\n <rdf:RDF>\n <rdf:Description rdf:about="http://www.cytoscape.org/">\n';
744
+ if (name !== null) {
745
+ yield ` <dc:title>${escapeXmlText(name)}</dc:title>
746
+ `;
747
+ }
748
+ if (description !== null) {
749
+ yield ` <dc:description>${escapeXmlText(description)}</dc:description>
750
+ `;
751
+ }
752
+ if (created !== null) {
753
+ yield ` <dc:date>${escapeXmlText(created)}</dc:date>
754
+ `;
755
+ }
756
+ yield " </rdf:Description>\n </rdf:RDF>\n </att>\n";
757
+ }
758
+ function* networksOf(snapshot, plan) {
759
+ const column = slot(plan.nodes, "networks");
760
+ if (column?.dtype !== "list") {
761
+ return;
762
+ }
763
+ const members = /* @__PURE__ */ new Map();
764
+ for (let u = 0; u < snapshot.nodeCount; u++) {
765
+ for (const id of column.isSet(u) ? column.sliceOf(u) : []) {
766
+ const list = members.get(String(id)) ?? [];
767
+ list.push(u);
768
+ members.set(String(id), list);
769
+ }
770
+ }
771
+ for (const [id, nodes] of members) {
772
+ yield ` <att>
773
+ <graph id="${escapeXmlAttribute(id)}">
774
+ `;
775
+ for (const u of nodes) {
776
+ yield ` <node xlink:href="#${escapeXmlAttribute(idText(snapshot.ids.idOf(u)))}"/>
777
+ `;
778
+ }
779
+ yield " </graph>\n </att>\n";
780
+ }
781
+ }
782
+ function* edgesOf(snapshot, plan) {
783
+ const { folding, weights } = plan;
784
+ const labelCol = slot(plan.edges, "label");
785
+ const graphicsCol = slot(plan.edges, "graphics");
786
+ const list = snapshot.edgeList();
787
+ let first = true;
788
+ for (let e = 0; e < snapshot.edgeCount; e++) {
789
+ if (folding.folded(e)) {
790
+ continue;
791
+ }
792
+ const u = list.src[e];
793
+ const v = list.dst[e];
794
+ const directed = snapshot.directed && folding.sourceDirected(e);
795
+ const id = cellOf(plan.edgeId, e);
796
+ const label = cellOf(labelCol, e);
797
+ const weight = weights.text(e);
798
+ yield ` <edge${id === null ? "" : ` id="${escapeXmlAttribute(scalarText(id))}"`}${label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`} source="${escapeXmlAttribute(idText(snapshot.ids.idOf(u)))}" target="${escapeXmlAttribute(idText(snapshot.ids.idOf(v)))}" cy:directed="${directed ? "1" : "0"}"${weight === null ? "" : ` weight="${weight}"`}${xmlAttributesOf(plan.edges, e)}>
799
+ `;
800
+ yield* attsOf(plan.edges, e, first, plan, " ");
801
+ yield* graphicsOf(cellOf(graphicsCol, e), [], " ");
802
+ yield " </edge>\n";
803
+ first = false;
804
+ }
805
+ }
806
+ function resolveEscapes(options) {
807
+ const value = options?.cytoscapeEscapes ?? false;
808
+ if (typeof value !== "boolean") {
809
+ throw new GraphFormatError("E_UNSUPPORTED", "option cytoscapeEscapes must be a boolean", {
810
+ option: "cytoscapeEscapes",
811
+ found: typeof value
812
+ });
813
+ }
814
+ return value;
815
+ }
816
+ function planFor(snapshot, options) {
817
+ const plan = planExport(snapshot, resolveExportOptions(options), resolveEscapes(options));
818
+ const illegal = plan.notes.find((n) => n.code === XGMML_LOSS.XML_ILLEGAL_CHAR);
819
+ if (illegal !== void 0) {
820
+ throw new GraphFormatError("E_COLUMN_TYPE", illegal.message, { code: illegal.code, column: illegal.column });
821
+ }
822
+ return plan;
823
+ }
824
+ const xgmmlExporter = Object.freeze({
825
+ format: FORMAT,
826
+ capabilities: CAPABILITIES,
827
+ check: (snapshot, options) => Object.freeze(planExport(snapshot, resolveExportOptions(options), resolveEscapes(options)).notes),
828
+ export: (snapshot, options) => encodeChunks(write(snapshot, options)),
829
+ exportToString: (snapshot, options) => joinText(write(snapshot, options))
830
+ });
831
+ export {
832
+ xgmmlExporter as x
833
+ };
834
+ //# sourceMappingURL=exporter-DIeGJXAZ.js.map