@graphty/graph-io 0.3.40 → 0.3.42
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.
- package/README.md +2 -0
- package/dist/chunks/{children-CL3Cy0ez.js → children-CA4coBi0.js} +36 -27
- package/dist/chunks/children-CA4coBi0.js.map +1 -0
- package/dist/chunks/{choose-CS3fvGT1.js → choose-DvpbdRuz.js} +2 -2
- package/dist/chunks/{choose-CS3fvGT1.js.map → choose-DvpbdRuz.js.map} +1 -1
- package/dist/chunks/{constants-DqKZT6cH.js → constants-fT3E8JYY.js} +2 -2
- package/dist/chunks/{constants-DqKZT6cH.js.map → constants-fT3E8JYY.js.map} +1 -1
- package/dist/chunks/{escape-BJRLd3vJ.js → escape-B62ZGM_a.js} +2 -2
- package/dist/chunks/{escape-BJRLd3vJ.js.map → escape-B62ZGM_a.js.map} +1 -1
- package/dist/chunks/{export-B-aVCwyG.js → export-rKLeGQMo.js} +404 -243
- package/dist/chunks/export-rKLeGQMo.js.map +1 -0
- package/dist/chunks/{exporter-6ocL_9x_.js → exporter-8hLNemFk.js} +4 -4
- package/dist/chunks/{exporter-6ocL_9x_.js.map → exporter-8hLNemFk.js.map} +1 -1
- package/dist/chunks/{exporter-BVXnV9-9.js → exporter-BWwEuOPT.js} +29 -17
- package/dist/chunks/exporter-BWwEuOPT.js.map +1 -0
- package/dist/chunks/{exporter-Bcp-l4Bo.js → exporter-CpRyHZ3H.js} +574 -475
- package/dist/chunks/exporter-CpRyHZ3H.js.map +1 -0
- package/dist/chunks/{exporter-SFYkDzD0.js → exporter-yLxKBvLE.js} +23 -20
- package/dist/chunks/{exporter-SFYkDzD0.js.map → exporter-yLxKBvLE.js.map} +1 -1
- package/dist/chunks/{importer-DcKB97kW.js → importer-BbNb7eNg.js} +111 -71
- package/dist/chunks/importer-BbNb7eNg.js.map +1 -0
- package/dist/chunks/{importer-D_srHyj6.js → importer-C98dpSH4.js} +5 -5
- package/dist/chunks/{importer-D_srHyj6.js.map → importer-C98dpSH4.js.map} +1 -1
- package/dist/chunks/{importer-BJlGAOht.js → importer-D794XUTe.js} +3 -3
- package/dist/chunks/{importer-BJlGAOht.js.map → importer-D794XUTe.js.map} +1 -1
- package/dist/chunks/{importer-AjwOJrn2.js → importer-Dz7tI8Sa.js} +202 -181
- package/dist/chunks/importer-Dz7tI8Sa.js.map +1 -0
- package/dist/chunks/{importer-DEp_fYjf.js → importer-Ht7LNg8L.js} +92 -64
- package/dist/chunks/importer-Ht7LNg8L.js.map +1 -0
- package/dist/chunks/{importer-CPqnIY8m.js → importer-WrGRZb0N.js} +42 -29
- package/dist/chunks/importer-WrGRZb0N.js.map +1 -0
- package/dist/chunks/{importer-BpuS3J8C.js → importer-xZ-3suY1.js} +74 -61
- package/dist/chunks/importer-xZ-3suY1.js.map +1 -0
- package/dist/chunks/{json-elements-DpO6AXIc.js → json-elements-DKSqpNW1.js} +3 -3
- package/dist/chunks/{json-elements-DpO6AXIc.js.map → json-elements-DKSqpNW1.js.map} +1 -1
- package/dist/chunks/{ontology-export-50L9DOV4.js → ontology-export-CtRXjg_i.js} +2 -2
- package/dist/chunks/{ontology-export-50L9DOV4.js.map → ontology-export-CtRXjg_i.js.map} +1 -1
- package/dist/chunks/{records-r3SFHz11.js → records-Cu4bxYOm.js} +69 -36
- package/dist/chunks/records-Cu4bxYOm.js.map +1 -0
- package/dist/chunks/{text-Bjfa1xYL.js → text-DHOJXnED.js} +20 -11
- package/dist/chunks/text-DHOJXnED.js.map +1 -0
- package/dist/csv.js +323 -241
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +1 -1
- package/dist/gexf.js +195 -97
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +170 -149
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +27 -27
- package/dist/graphml.js +2 -2
- package/dist/json.js +1 -1
- package/dist/neo4j.js +103 -65
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/children.d.ts.map +1 -1
- package/dist/src/children.js +50 -27
- package/dist/src/children.js.map +1 -1
- package/dist/src/common/attributes.d.ts.map +1 -1
- package/dist/src/common/attributes.js +86 -42
- package/dist/src/common/attributes.js.map +1 -1
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +358 -184
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/lists.js +30 -15
- package/dist/src/common/lists.js.map +1 -1
- package/dist/src/common/text.d.ts +7 -0
- package/dist/src/common/text.d.ts.map +1 -1
- package/dist/src/common/text.js +15 -7
- package/dist/src/common/text.js.map +1 -1
- package/dist/src/common/zip.d.ts.map +1 -1
- package/dist/src/common/zip.js +36 -19
- package/dist/src/common/zip.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +288 -146
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/csv/importer.d.ts.map +1 -1
- package/dist/src/formats/csv/importer.js +129 -80
- package/dist/src/formats/csv/importer.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +78 -36
- package/dist/src/formats/csv/records.js.map +1 -1
- package/dist/src/formats/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +11 -8
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/dot/tokenizer.d.ts +39 -0
- package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
- package/dist/src/formats/dot/tokenizer.js +112 -66
- package/dist/src/formats/dot/tokenizer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +65 -37
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +138 -50
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +51 -35
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +103 -58
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +17 -8
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +34 -24
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +17 -13
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/tree.js +23 -14
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +22 -10
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +54 -20
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +38 -21
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +536 -343
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/obographs.js +29 -17
- package/dist/src/formats/json/obographs.js.map +1 -1
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +73 -43
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/neo4j/header.d.ts.map +1 -1
- package/dist/src/formats/neo4j/header.js +37 -16
- package/dist/src/formats/neo4j/header.js.map +1 -1
- package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
- package/dist/src/formats/neo4j/importer.js +21 -11
- package/dist/src/formats/neo4j/importer.js.map +1 -1
- package/dist/src/formats/obo/exporter.d.ts.map +1 -1
- package/dist/src/formats/obo/exporter.js +18 -7
- package/dist/src/formats/obo/exporter.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +142 -73
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +26 -15
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +85 -58
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +7 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +79 -40
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +38 -12
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +38 -18
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/sniff.js +109 -57
- package/dist/src/sniff.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/package.json +2 -2
- package/src/children.ts +54 -27
- package/src/common/attributes.ts +118 -49
- package/src/common/input.ts +439 -197
- package/src/common/lists.ts +29 -15
- package/src/common/text.ts +24 -15
- package/src/common/zip.ts +47 -18
- package/src/formats/csv/exporter.ts +377 -175
- package/src/formats/csv/importer.ts +155 -84
- package/src/formats/csv/records.ts +90 -35
- package/src/formats/cys/tables.ts +11 -10
- package/src/formats/dot/tokenizer.ts +118 -68
- package/src/formats/gexf/exporter.ts +67 -36
- package/src/formats/gexf/importer.ts +173 -63
- package/src/formats/gml/exporter.ts +78 -82
- package/src/formats/gml/importer.ts +119 -68
- package/src/formats/gml/syntax.ts +18 -8
- package/src/formats/graphml/exporter.ts +44 -24
- package/src/formats/graphml/importer.ts +18 -11
- package/src/formats/graphml/tree.ts +22 -12
- package/src/formats/graphml/yfiles.ts +23 -10
- package/src/formats/json/dialect.ts +61 -22
- package/src/formats/json/exporter.ts +40 -21
- package/src/formats/json/importer.ts +701 -385
- package/src/formats/json/obographs.ts +35 -15
- package/src/formats/neo4j/exporter.ts +79 -41
- package/src/formats/neo4j/header.ts +50 -16
- package/src/formats/neo4j/importer.ts +21 -10
- package/src/formats/obo/exporter.ts +34 -17
- package/src/formats/pajek/exporter.ts +180 -117
- package/src/formats/pajek/importer.ts +27 -15
- package/src/formats/pajek/syntax.ts +99 -58
- package/src/formats/xgmml/emit.ts +88 -40
- package/src/formats/xgmml/exporter.ts +40 -12
- package/src/formats/xgmml/importer.ts +45 -23
- package/src/sniff.ts +115 -59
- package/dist/chunks/children-CL3Cy0ez.js.map +0 -1
- package/dist/chunks/export-B-aVCwyG.js.map +0 -1
- package/dist/chunks/exporter-BVXnV9-9.js.map +0 -1
- package/dist/chunks/exporter-Bcp-l4Bo.js.map +0 -1
- package/dist/chunks/importer-AjwOJrn2.js.map +0 -1
- package/dist/chunks/importer-BpuS3J8C.js.map +0 -1
- package/dist/chunks/importer-CPqnIY8m.js.map +0 -1
- package/dist/chunks/importer-DEp_fYjf.js.map +0 -1
- package/dist/chunks/importer-DcKB97kW.js.map +0 -1
- package/dist/chunks/records-r3SFHz11.js.map +0 -1
- package/dist/chunks/text-Bjfa1xYL.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
|
|
2
|
-
import { c as capabilities, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, o as DUPLICATE_ATTRIBUTE_CODE, g as UNKNOWN_ELEMENT_CODE, b5 as EMPTY_COLUMN_DROPPED_CODE, ai as PARENT_CYCLE_CODE, P as PRECISION_CODE, w as UNKNOWN_ENCODING_CODE, a2 as JSON_NONSTANDARD_NUMBER_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, O as OPTION_IGNORED_CODE, S as SINK_OPTION_CODE, H as HYPEREDGE_CODE, ad as TOO_LARGE_CODE, i as DANGLING_REFERENCE_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, I as ID_MERGED_CODE, m as DUPLICATE_EDGE_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, a3 as BAD_VALUE_CODE, s as MISSING_ENDPOINT_CODE, t as MISSING_ID_CODE, ak as SYNTAX_CODE, E as EMPTY_INPUT_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, bB as readText, b as plural, ao as reportSinkOptions, an as reportUnusedOptions, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, $ as agree, as as weightFromValue, a0 as uniqueColumnName, a7 as chooseGraph, ap as graphChosen, a1 as declareResolved, aB as GRAPH_COLUMN_AS_METADATA_CODE, aC as TYPEDEF_NODES_CODE, aD as RELATION_ASSUMED_CODE, at as COLUMN_AS_PROPERTY_VALUE_CODE, p as pairFolding, e as explicitWeights, bd as NONFINITE_AS_NULL_CODE, L as LOSS, b3 as DIRECTION_DROPPED_CODE, aA as NODE_ORDER_CODE, r as resolveExportOptions, b_ as otherFormatDialect, a as checkCapabilities, bD as countMixedEdges, aa as formatF32, ab as formatF64 } from "./export-
|
|
3
|
-
import { M as MAYBE_UNSAFE_INTEGER, j as MAYBE_INEXACT_EXPONENT, l as rewriteNumbers, m as findDuplicateKeys, f as flipY } from "./json-elements-
|
|
2
|
+
import { c as capabilities, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, o as DUPLICATE_ATTRIBUTE_CODE, g as UNKNOWN_ELEMENT_CODE, b5 as EMPTY_COLUMN_DROPPED_CODE, ai as PARENT_CYCLE_CODE, P as PRECISION_CODE, w as UNKNOWN_ENCODING_CODE, a2 as JSON_NONSTANDARD_NUMBER_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, O as OPTION_IGNORED_CODE, S as SINK_OPTION_CODE, H as HYPEREDGE_CODE, ad as TOO_LARGE_CODE, i as DANGLING_REFERENCE_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, I as ID_MERGED_CODE, m as DUPLICATE_EDGE_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, a3 as BAD_VALUE_CODE, s as MISSING_ENDPOINT_CODE, t as MISSING_ID_CODE, ak as SYNTAX_CODE, E as EMPTY_INPUT_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, bB as readText, b as plural, ao as reportSinkOptions, an as reportUnusedOptions, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, $ as agree, as as weightFromValue, a0 as uniqueColumnName, a7 as chooseGraph, ap as graphChosen, a1 as declareResolved, aB as GRAPH_COLUMN_AS_METADATA_CODE, aC as TYPEDEF_NODES_CODE, aD as RELATION_ASSUMED_CODE, at as COLUMN_AS_PROPERTY_VALUE_CODE, p as pairFolding, e as explicitWeights, bd as NONFINITE_AS_NULL_CODE, L as LOSS, b3 as DIRECTION_DROPPED_CODE, aA as NODE_ORDER_CODE, r as resolveExportOptions, b_ as otherFormatDialect, a as checkCapabilities, bD as countMixedEdges, aa as formatF32, ab as formatF64 } from "./export-rKLeGQMo.js";
|
|
3
|
+
import { M as MAYBE_UNSAFE_INTEGER, j as MAYBE_INEXACT_EXPONENT, l as rewriteNumbers, m as findDuplicateKeys, f as flipY } from "./json-elements-DKSqpNW1.js";
|
|
4
4
|
import { j as joinText, e as encodeChunks, i as indentUnit } from "./writer-DxjgHwSe.js";
|
|
5
|
-
import { t as trimTrailingZeros } from "./text-
|
|
6
|
-
import { d as OBOGRAPHS_PREDICATE_TAGS, g as compactOboIri, o as oboColumnDecl, P as PLACEHOLDER_COLUMN, h as synonymScopeOf, O as OBO_NODE_COLUMNS, c as capabilityNotes, s as slotColumn, e as emptyColumnNotes, j as OBO_PURL, f as framelessNodes, m as movedNodes, U as UNWRITTEN_ROLES, n as notePropertyColumn, a as cellOf, v as valuesOf, k as OBO_IN_OWL, b as fitsVocabulary, t as textOf, S as SYNONYM_SCOPES } from "./ontology-export-
|
|
5
|
+
import { t as trimTrailingZeros } from "./text-DHOJXnED.js";
|
|
6
|
+
import { d as OBOGRAPHS_PREDICATE_TAGS, g as compactOboIri, o as oboColumnDecl, P as PLACEHOLDER_COLUMN, h as synonymScopeOf, O as OBO_NODE_COLUMNS, c as capabilityNotes, s as slotColumn, e as emptyColumnNotes, j as OBO_PURL, f as framelessNodes, m as movedNodes, U as UNWRITTEN_ROLES, n as notePropertyColumn, a as cellOf, v as valuesOf, k as OBO_IN_OWL, b as fitsVocabulary, t as textOf, S as SYNONYM_SCOPES } from "./ontology-export-CtRXjg_i.js";
|
|
7
7
|
const JSON_DIALECTS = Object.freeze([
|
|
8
8
|
"node-link",
|
|
9
9
|
"d3",
|
|
@@ -43,6 +43,10 @@ function sniffJsonDialect(root) {
|
|
|
43
43
|
if (!isJsonObject(root)) {
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
|
+
const decided = sniffWrapperDialect(root) ?? sniffEdgelessDialect(root);
|
|
47
|
+
return decided === void 0 ? sniffEdgeListDialect(root) : decided;
|
|
48
|
+
}
|
|
49
|
+
function sniffWrapperDialect(root) {
|
|
46
50
|
if (hasKey(root, "elements")) {
|
|
47
51
|
return "cytoscape";
|
|
48
52
|
}
|
|
@@ -52,33 +56,42 @@ function sniffJsonDialect(root) {
|
|
|
52
56
|
if (Array.isArray(root.graphs)) {
|
|
53
57
|
return root.graphs.some((g) => isJsonObject(g) && isOboGraph(g)) ? "obographs" : "jgf";
|
|
54
58
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
function sniffEdgelessDialect(root) {
|
|
62
|
+
if (hasKey(root, "edges") || hasKey(root, "links")) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
if (hasKey(root, "nodes")) {
|
|
66
|
+
return hasKey(root, "adjacency") ? "adjacency" : void 0;
|
|
62
67
|
}
|
|
68
|
+
return hasKey(root, "children") ? "tree" : null;
|
|
69
|
+
}
|
|
70
|
+
function sniffEdgeListDialect(root) {
|
|
63
71
|
const firstNode = firstJsonObject(root.nodes);
|
|
64
72
|
const firstEdge = firstJsonObject(hasKey(root, "edges") ? root.edges : root.links);
|
|
65
73
|
if (isJsonObject(root.options) && (hasKey(root.options, "type") || hasKey(root.options, "multi"))) {
|
|
66
74
|
return "graphology";
|
|
67
75
|
}
|
|
68
76
|
const networkx = hasKey(root, "links") || hasKey(root, "directed") || hasKey(root, "multigraph") || hasKey(root, "graph");
|
|
69
|
-
|
|
77
|
+
const record = networkx ? void 0 : sniffRecordDialect(firstNode, firstEdge);
|
|
78
|
+
if (record !== void 0) {
|
|
79
|
+
return record;
|
|
80
|
+
}
|
|
81
|
+
const bare = !hasKey(root, "directed") && !hasKey(root, "multigraph") && !hasKey(root, "graph");
|
|
82
|
+
return bare && hasKey(root, "links") ? "d3" : "node-link";
|
|
83
|
+
}
|
|
84
|
+
function sniffRecordDialect(firstNode, firstEdge) {
|
|
85
|
+
if (firstNode !== null && hasKey(firstNode, "key") && !hasKey(firstNode, "id")) {
|
|
70
86
|
return "graphology";
|
|
71
87
|
}
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
return "graphology";
|
|
75
|
-
}
|
|
88
|
+
if (firstEdge === null) {
|
|
89
|
+
return void 0;
|
|
76
90
|
}
|
|
77
|
-
if (!
|
|
78
|
-
return "
|
|
91
|
+
if (!hasKey(firstEdge, "from")) {
|
|
92
|
+
return hasKey(firstEdge, "undirected") || isJsonObject(firstEdge.attributes) ? "graphology" : void 0;
|
|
79
93
|
}
|
|
80
|
-
|
|
81
|
-
return bare && hasKey(root, "links") ? "d3" : "node-link";
|
|
94
|
+
return hasKey(firstEdge, "to") && !hasKey(firstEdge, "source") ? "vis" : void 0;
|
|
82
95
|
}
|
|
83
96
|
const OBOGRAPHS_NODE_TYPES = /* @__PURE__ */ new Set(["CLASS", "INDIVIDUAL", "PROPERTY"]);
|
|
84
97
|
function isOboGraph(graph) {
|
|
@@ -373,38 +386,42 @@ function skeletonOf(text) {
|
|
|
373
386
|
}
|
|
374
387
|
const root = {};
|
|
375
388
|
for (const key of rootKeys) {
|
|
376
|
-
|
|
377
|
-
case "graph":
|
|
378
|
-
case "options":
|
|
379
|
-
root[key] = objectOf(keys.get(key));
|
|
380
|
-
break;
|
|
381
|
-
case "graphs": {
|
|
382
|
-
const nodes = keys.get("graphs[0].nodes[]");
|
|
383
|
-
const edges = keys.get("graphs[0].edges[]");
|
|
384
|
-
const graph = {};
|
|
385
|
-
if (nodes !== void 0) {
|
|
386
|
-
graph.nodes = [objectOf(nodes)];
|
|
387
|
-
}
|
|
388
|
-
if (edges !== void 0) {
|
|
389
|
-
graph.edges = [objectOf(edges)];
|
|
390
|
-
}
|
|
391
|
-
root[key] = nodes === void 0 && edges === void 0 ? [] : [graph];
|
|
392
|
-
break;
|
|
393
|
-
}
|
|
394
|
-
case "nodes":
|
|
395
|
-
case "edges":
|
|
396
|
-
case "links": {
|
|
397
|
-
const first = keys.get(`${key}[0]`);
|
|
398
|
-
root[key] = first === void 0 ? [] : [objectOf(first)];
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
default:
|
|
402
|
-
root[key] = true;
|
|
403
|
-
break;
|
|
404
|
-
}
|
|
389
|
+
root[key] = placeholderOf(key, keys);
|
|
405
390
|
}
|
|
406
391
|
return root;
|
|
407
392
|
}
|
|
393
|
+
function placeholderOf(key, keys) {
|
|
394
|
+
switch (key) {
|
|
395
|
+
case "graph":
|
|
396
|
+
case "options":
|
|
397
|
+
return objectOf(keys.get(key));
|
|
398
|
+
case "graphs":
|
|
399
|
+
return graphsPlaceholder(keys);
|
|
400
|
+
case "nodes":
|
|
401
|
+
case "edges":
|
|
402
|
+
case "links": {
|
|
403
|
+
const first = keys.get(`${key}[0]`);
|
|
404
|
+
return first === void 0 ? [] : [objectOf(first)];
|
|
405
|
+
}
|
|
406
|
+
default:
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function graphsPlaceholder(keys) {
|
|
411
|
+
const nodes = keys.get("graphs[0].nodes[]");
|
|
412
|
+
const edges = keys.get("graphs[0].edges[]");
|
|
413
|
+
if (nodes === void 0 && edges === void 0) {
|
|
414
|
+
return [];
|
|
415
|
+
}
|
|
416
|
+
const graph = {};
|
|
417
|
+
if (nodes !== void 0) {
|
|
418
|
+
graph.nodes = [objectOf(nodes)];
|
|
419
|
+
}
|
|
420
|
+
if (edges !== void 0) {
|
|
421
|
+
graph.edges = [objectOf(edges)];
|
|
422
|
+
}
|
|
423
|
+
return [graph];
|
|
424
|
+
}
|
|
408
425
|
function objectOf(names) {
|
|
409
426
|
const out = {};
|
|
410
427
|
if (names !== void 0) {
|
|
@@ -421,28 +438,6 @@ function scanKeys(text) {
|
|
|
421
438
|
const counts = [];
|
|
422
439
|
let pendingKey = null;
|
|
423
440
|
let expectingKey = false;
|
|
424
|
-
const pathOf = () => {
|
|
425
|
-
const depth = kinds.length;
|
|
426
|
-
if (depth === 1) {
|
|
427
|
-
return kinds[0] === "object" ? "" : null;
|
|
428
|
-
}
|
|
429
|
-
if (depth === 2 && kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
|
|
430
|
-
return "nodes[0]";
|
|
431
|
-
}
|
|
432
|
-
if (depth === 2 && kinds[0] === "object" && kinds[1] === "object") {
|
|
433
|
-
return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
|
|
434
|
-
}
|
|
435
|
-
if (depth === 5 && kinds.join() === "object,array,object,array,object" && labels[1] === "graphs" && labels[2] === "0" && (labels[3] === "nodes" || labels[3] === "edges")) {
|
|
436
|
-
return labels[3] === "nodes" ? "graphs[0].nodes[]" : "graphs[0].edges[]";
|
|
437
|
-
}
|
|
438
|
-
if (depth === 3 && kinds[0] === "object" && kinds[1] === "array" && kinds[2] === "object") {
|
|
439
|
-
const section = labels[1];
|
|
440
|
-
if ((section === "nodes" || section === "edges" || section === "links") && labels[2] === "0") {
|
|
441
|
-
return `${section}[0]`;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return null;
|
|
445
|
-
};
|
|
446
441
|
let i = 0;
|
|
447
442
|
const n = text.length;
|
|
448
443
|
while (i < n) {
|
|
@@ -478,7 +473,7 @@ function scanKeys(text) {
|
|
|
478
473
|
pendingKey = null;
|
|
479
474
|
} else if (ch === ":") {
|
|
480
475
|
if (pendingKey !== null) {
|
|
481
|
-
const path =
|
|
476
|
+
const path = keyPathOf(kinds, labels);
|
|
482
477
|
if (path !== null) {
|
|
483
478
|
let set = found.get(path);
|
|
484
479
|
if (set === void 0) {
|
|
@@ -500,6 +495,45 @@ function scanKeys(text) {
|
|
|
500
495
|
}
|
|
501
496
|
return found;
|
|
502
497
|
}
|
|
498
|
+
function keyPathOf(kinds, labels) {
|
|
499
|
+
switch (kinds.length) {
|
|
500
|
+
case 1:
|
|
501
|
+
return kinds[0] === "object" ? "" : null;
|
|
502
|
+
case 2:
|
|
503
|
+
return nestedObjectPath(kinds, labels);
|
|
504
|
+
case 3:
|
|
505
|
+
return sectionElementPath(kinds, labels);
|
|
506
|
+
case 5:
|
|
507
|
+
return graphsMemberPath(kinds, labels);
|
|
508
|
+
default:
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
function nestedObjectPath(kinds, labels) {
|
|
513
|
+
if (kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
|
|
514
|
+
return "nodes[0]";
|
|
515
|
+
}
|
|
516
|
+
if (kinds[0] === "object" && kinds[1] === "object") {
|
|
517
|
+
return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
|
|
518
|
+
}
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
function sectionElementPath(kinds, labels) {
|
|
522
|
+
if (kinds[0] !== "object" || kinds[1] !== "array" || kinds[2] !== "object" || labels[2] !== "0") {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
const section = labels[1];
|
|
526
|
+
return section === "nodes" || section === "edges" || section === "links" ? `${section}[0]` : null;
|
|
527
|
+
}
|
|
528
|
+
function graphsMemberPath(kinds, labels) {
|
|
529
|
+
if (kinds.join() !== "object,array,object,array,object" || labels[1] !== "graphs" || labels[2] !== "0") {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
if (labels[3] === "nodes") {
|
|
533
|
+
return "graphs[0].nodes[]";
|
|
534
|
+
}
|
|
535
|
+
return labels[3] === "edges" ? "graphs[0].edges[]" : null;
|
|
536
|
+
}
|
|
503
537
|
function scanString(text, from) {
|
|
504
538
|
let i = from;
|
|
505
539
|
while (i < text.length) {
|
|
@@ -2076,18 +2110,7 @@ function importAdjacency(ctx, root) {
|
|
|
2076
2110
|
const multigraph = hasKey(root, "multigraph") ? flagOf(root.multigraph, "multigraph", false, report) : null;
|
|
2077
2111
|
ctx.setHeader(directed);
|
|
2078
2112
|
ctx.writeGraphDict(isPairList(root.graph) ? Object.fromEntries(root.graph) : root.graph, "graph");
|
|
2079
|
-
|
|
2080
|
-
if (key !== "nodes" && key !== "adjacency" && key !== "directed" && key !== "multigraph" && key !== "graph") {
|
|
2081
|
-
report.warning(
|
|
2082
|
-
"unsupported",
|
|
2083
|
-
JSON_ISSUE.UNREAD_KEY,
|
|
2084
|
-
`top-level key ${key} (${describe(root[key])}) is not read; dropped`,
|
|
2085
|
-
{
|
|
2086
|
-
element: key
|
|
2087
|
-
}
|
|
2088
|
-
);
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2113
|
+
reportUnreadAdjacencyKeys(ctx, root);
|
|
2091
2114
|
const lists = adjacency ?? [];
|
|
2092
2115
|
ctx.sink.reserve(
|
|
2093
2116
|
nodes.length,
|
|
@@ -2095,90 +2118,120 @@ function importAdjacency(ctx, root) {
|
|
|
2095
2118
|
);
|
|
2096
2119
|
const idKey = ctx.json.nodeIdKey ?? "id";
|
|
2097
2120
|
ctx.reportNodeIdFrom("adjacency", `the ${JSON.stringify(idKey)} key`);
|
|
2098
|
-
const owners = [];
|
|
2099
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
2100
|
-
const element = `nodes[${i}]`;
|
|
2101
|
-
const record = nodes[i];
|
|
2102
|
-
let pushed = null;
|
|
2103
|
-
if (!isJsonObject(record)) {
|
|
2104
|
-
ctx.badElement("node", element);
|
|
2105
|
-
} else {
|
|
2106
|
-
const id = ctx.coerceId(hasKey(record, idKey) ? record[idKey] : void 0, element);
|
|
2107
|
-
if (id === null) {
|
|
2108
|
-
ctx.countSkipped("node");
|
|
2109
|
-
} else {
|
|
2110
|
-
const index = ctx.pushNode(id, element);
|
|
2111
|
-
if (index >= 0) {
|
|
2112
|
-
pushed = id;
|
|
2113
|
-
writeFlat(ctx.nodes, index, record, id, (key) => key !== idKey);
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
owners.push(pushed);
|
|
2118
|
-
}
|
|
2121
|
+
const owners = nodes.map((record, i) => pushAdjacencyNode(ctx, record, `nodes[${i}]`, idKey));
|
|
2119
2122
|
throwIfAborted(ctx.options.signal);
|
|
2120
|
-
const
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2123
|
+
const reading = {
|
|
2124
|
+
owners,
|
|
2125
|
+
nodeCount: nodes.length,
|
|
2126
|
+
directed,
|
|
2127
|
+
kind: ctx.uniformKind(),
|
|
2128
|
+
idKey,
|
|
2129
|
+
// undirected: entries read once whose mirror is still to come, by pair and key, with their attributes
|
|
2130
|
+
pending: /* @__PURE__ */ new Map(),
|
|
2131
|
+
disagreeing: 0
|
|
2132
|
+
};
|
|
2124
2133
|
for (let i = 0; i < lists.length; i++) {
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2134
|
+
readAdjacencyList(ctx, reading, i, lists[i]);
|
|
2135
|
+
}
|
|
2136
|
+
reportAdjacencyShape(
|
|
2137
|
+
ctx,
|
|
2138
|
+
nodes.length,
|
|
2139
|
+
adjacency === null ? null : lists.length,
|
|
2140
|
+
reading.disagreeing,
|
|
2141
|
+
reading.pending
|
|
2142
|
+
);
|
|
2143
|
+
ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
|
|
2144
|
+
}
|
|
2145
|
+
const ADJACENCY_DOCUMENT_KEYS = /* @__PURE__ */ new Set(["nodes", "adjacency", "directed", "multigraph", "graph"]);
|
|
2146
|
+
function reportUnreadAdjacencyKeys(ctx, root) {
|
|
2147
|
+
for (const key of Object.keys(root)) {
|
|
2148
|
+
if (!ADJACENCY_DOCUMENT_KEYS.has(key)) {
|
|
2149
|
+
ctx.report.warning(
|
|
2150
|
+
"unsupported",
|
|
2151
|
+
JSON_ISSUE.UNREAD_KEY,
|
|
2152
|
+
`top-level key ${key} (${describe(root[key])}) is not read; dropped`,
|
|
2138
2153
|
{
|
|
2139
|
-
element
|
|
2154
|
+
element: key
|
|
2140
2155
|
}
|
|
2141
2156
|
);
|
|
2142
|
-
report.counts.skippedEdges += list.length;
|
|
2143
|
-
continue;
|
|
2144
2157
|
}
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
function pushAdjacencyNode(ctx, record, element, idKey) {
|
|
2161
|
+
if (!isJsonObject(record)) {
|
|
2162
|
+
ctx.badElement("node", element);
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
const id = ctx.coerceId(hasKey(record, idKey) ? record[idKey] : void 0, element);
|
|
2166
|
+
if (id === null) {
|
|
2167
|
+
ctx.countSkipped("node");
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2170
|
+
const index = ctx.pushNode(id, element);
|
|
2171
|
+
if (index < 0) {
|
|
2172
|
+
return null;
|
|
2173
|
+
}
|
|
2174
|
+
writeFlat(ctx.nodes, index, record, id, (key) => key !== idKey);
|
|
2175
|
+
return id;
|
|
2176
|
+
}
|
|
2177
|
+
function readAdjacencyList(ctx, reading, i, list) {
|
|
2178
|
+
const { report } = ctx;
|
|
2179
|
+
const element = `adjacency[${i}]`;
|
|
2180
|
+
if (!Array.isArray(list)) {
|
|
2181
|
+
report.error("validation-error", JSON_ISSUE.BAD_ELEMENT, `${element} is not an array`, { element });
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
const source = i < reading.owners.length ? reading.owners[i] : null;
|
|
2185
|
+
if (source === null) {
|
|
2186
|
+
const why = i < reading.nodeCount ? `nodes[${i}] was skipped` : `there is no nodes[${i}]`;
|
|
2187
|
+
report.error(
|
|
2188
|
+
"missing-value",
|
|
2189
|
+
JSON_ISSUE.BAD_INDEX,
|
|
2190
|
+
`${element}: ${why}; its ${list.length} edge${plural(list.length)} ${agree(list.length, "is", "are")} skipped`,
|
|
2191
|
+
{
|
|
2192
|
+
element
|
|
2151
2193
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2194
|
+
);
|
|
2195
|
+
report.counts.skippedEdges += list.length;
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
for (let j = 0; j < list.length; j++) {
|
|
2199
|
+
readAdjacencyEntry(ctx, reading, source, list[j], element, `${element}[${j}]`);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
function readAdjacencyEntry(ctx, reading, source, record, element, entry) {
|
|
2203
|
+
const { idKey } = reading;
|
|
2204
|
+
if (!isJsonObject(record)) {
|
|
2205
|
+
ctx.badElement("edge", entry);
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2208
|
+
if (!hasKey(record, idKey)) {
|
|
2209
|
+
ctx.missingEndpoint(entry, idKey);
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
try {
|
|
2213
|
+
const target = ctx.coerceId(record[idKey], `${entry}.${idKey}`);
|
|
2214
|
+
if (target === null) {
|
|
2215
|
+
ctx.countSkipped("edge");
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
if (!reading.directed) {
|
|
2219
|
+
const mirror = mirroredEntry(reading.pending, source, target, record, idKey);
|
|
2220
|
+
reading.disagreeing += mirror === "disagrees" ? 1 : 0;
|
|
2221
|
+
if (mirror !== "new") {
|
|
2222
|
+
return;
|
|
2155
2223
|
}
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
if (!directed) {
|
|
2163
|
-
const mirror = mirroredEntry(pending, source, target, record, idKey);
|
|
2164
|
-
disagreeing += mirror === "disagrees" ? 1 : 0;
|
|
2165
|
-
if (mirror !== "new") {
|
|
2166
|
-
continue;
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
const edge = ctx.pushEdge(source, target, kind, ctx.weightOf(record), entry);
|
|
2170
|
-
for (const key of Object.keys(record)) {
|
|
2171
|
-
if (key !== idKey && key !== weightFrom) {
|
|
2172
|
-
ctx.edges.write(edge, key, record[key], SUFFIX.data, element);
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
} catch (err) {
|
|
2176
|
-
ctx.skip(err, "edge", entry);
|
|
2224
|
+
}
|
|
2225
|
+
const edge = ctx.pushEdge(source, target, reading.kind, ctx.weightOf(record), entry);
|
|
2226
|
+
const { weightFrom } = ctx.options;
|
|
2227
|
+
for (const key of Object.keys(record)) {
|
|
2228
|
+
if (key !== idKey && key !== weightFrom) {
|
|
2229
|
+
ctx.edges.write(edge, key, record[key], SUFFIX.data, element);
|
|
2177
2230
|
}
|
|
2178
2231
|
}
|
|
2232
|
+
} catch (err) {
|
|
2233
|
+
ctx.skip(err, "edge", entry);
|
|
2179
2234
|
}
|
|
2180
|
-
reportAdjacencyShape(ctx, nodes.length, adjacency === null ? null : lists.length, disagreeing, pending);
|
|
2181
|
-
ctx.setMeta({}, { declaredMultigraph: multigraph, ...ctx.weightOriginPatch() });
|
|
2182
2235
|
}
|
|
2183
2236
|
function reportAdjacencyShape(ctx, nodes, lists, disagreeing, pending) {
|
|
2184
2237
|
const { report } = ctx;
|
|
@@ -2298,107 +2351,120 @@ function importGraphology(ctx, root) {
|
|
|
2298
2351
|
element: "options"
|
|
2299
2352
|
});
|
|
2300
2353
|
}
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
({ type } = options);
|
|
2304
|
-
} else {
|
|
2305
|
-
if (options.type !== void 0 && options.type !== null) {
|
|
2306
|
-
report.warning(
|
|
2307
|
-
"validation-error",
|
|
2308
|
-
JSON_ISSUE.BAD_FLAG,
|
|
2309
|
-
`options.type ${describe(options.type)} is not directed, undirected or mixed; mixed assumed`,
|
|
2310
|
-
{ element: "options.type" }
|
|
2311
|
-
);
|
|
2312
|
-
}
|
|
2313
|
-
type = "mixed";
|
|
2314
|
-
}
|
|
2315
|
-
let directed;
|
|
2316
|
-
if (type === "mixed") {
|
|
2317
|
-
const objects = edges.filter((edge) => isJsonObject(edge));
|
|
2318
|
-
const undirectedEdges = objects.filter((edge) => edge.undirected === true).length;
|
|
2319
|
-
directed = objects.length === 0 ? ctx.defaultDirected("graphology") : undirectedEdges < objects.length;
|
|
2320
|
-
} else {
|
|
2321
|
-
directed = type === "directed";
|
|
2322
|
-
}
|
|
2323
|
-
ctx.setHeader(directed);
|
|
2354
|
+
const type = graphologyType(ctx, options);
|
|
2355
|
+
ctx.setHeader(graphologyDirected(ctx, type, edges));
|
|
2324
2356
|
const multi = hasKey(options, "multi") ? flagOf(options.multi, "options.multi", false, report) : null;
|
|
2325
2357
|
const allowSelfLoops = hasKey(options, "allowSelfLoops") ? flagOf(options.allowSelfLoops, "options.allowSelfLoops", true, report) : void 0;
|
|
2326
2358
|
ctx.writeGraphDict(root.attributes, "attributes");
|
|
2327
2359
|
ctx.reportNodeIdFrom("graphology", "the node key");
|
|
2328
2360
|
ctx.sink.reserve(nodes.length, edges.length);
|
|
2329
2361
|
for (let i = 0; i < nodes.length; i++) {
|
|
2330
|
-
|
|
2331
|
-
const record = nodes[i];
|
|
2332
|
-
if (!isJsonObject(record)) {
|
|
2333
|
-
ctx.badElement("node", element);
|
|
2334
|
-
continue;
|
|
2335
|
-
}
|
|
2336
|
-
const id = ctx.coerceId(hasKey(record, "key") ? record.key : void 0, element);
|
|
2337
|
-
if (id === null) {
|
|
2338
|
-
ctx.countSkipped("node");
|
|
2339
|
-
continue;
|
|
2340
|
-
}
|
|
2341
|
-
pushNestedNode(ctx, id, record, "attributes", GRAPHOLOGY_NODE_KEYS, element);
|
|
2362
|
+
pushGraphologyNode(ctx, nodes[i], `nodes[${i}]`);
|
|
2342
2363
|
}
|
|
2343
2364
|
throwIfAborted(ctx.options.signal);
|
|
2344
|
-
const
|
|
2345
|
-
|
|
2346
|
-
|
|
2365
|
+
const reading = {
|
|
2366
|
+
ids: ctx.declareEdgeIds(edges, (edge) => edge.key, "key", true),
|
|
2367
|
+
type,
|
|
2368
|
+
allowSelfLoops,
|
|
2369
|
+
// what the edges do against the declared options: graphology itself refuses such a document
|
|
2370
|
+
violations: { selfLoops: 0, parallels: 0, flags: 0 },
|
|
2371
|
+
pairs: multi === false ? /* @__PURE__ */ new Set() : null
|
|
2372
|
+
};
|
|
2347
2373
|
for (let i = 0; i < edges.length; i++) {
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2374
|
+
readGraphologyEdge(ctx, reading, edges[i], `edges[${i}]`);
|
|
2375
|
+
}
|
|
2376
|
+
reportGraphologyViolations(ctx, reading.violations, type);
|
|
2377
|
+
ctx.setMeta({ dialect: "graphology", allowSelfLoops }, { declaredMultigraph: multi, ...ctx.weightOriginPatch() });
|
|
2378
|
+
}
|
|
2379
|
+
function graphologyType(ctx, options) {
|
|
2380
|
+
if (options.type === "directed" || options.type === "undirected" || options.type === "mixed") {
|
|
2381
|
+
return options.type;
|
|
2382
|
+
}
|
|
2383
|
+
if (options.type !== void 0 && options.type !== null) {
|
|
2384
|
+
ctx.report.warning(
|
|
2385
|
+
"validation-error",
|
|
2386
|
+
JSON_ISSUE.BAD_FLAG,
|
|
2387
|
+
`options.type ${describe(options.type)} is not directed, undirected or mixed; mixed assumed`,
|
|
2388
|
+
{ element: "options.type" }
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
return "mixed";
|
|
2392
|
+
}
|
|
2393
|
+
function graphologyDirected(ctx, type, edges) {
|
|
2394
|
+
if (type !== "mixed") {
|
|
2395
|
+
return type === "directed";
|
|
2396
|
+
}
|
|
2397
|
+
const objects = edges.filter((edge) => isJsonObject(edge));
|
|
2398
|
+
const undirectedEdges = objects.filter((edge) => edge.undirected === true).length;
|
|
2399
|
+
return objects.length === 0 ? ctx.defaultDirected("graphology") : undirectedEdges < objects.length;
|
|
2400
|
+
}
|
|
2401
|
+
function pushGraphologyNode(ctx, record, element) {
|
|
2402
|
+
if (!isJsonObject(record)) {
|
|
2403
|
+
ctx.badElement("node", element);
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
const id = ctx.coerceId(hasKey(record, "key") ? record.key : void 0, element);
|
|
2407
|
+
if (id === null) {
|
|
2408
|
+
ctx.countSkipped("node");
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
pushNestedNode(ctx, id, record, "attributes", GRAPHOLOGY_NODE_KEYS, element);
|
|
2412
|
+
}
|
|
2413
|
+
function readGraphologyEdge(ctx, reading, record, element) {
|
|
2414
|
+
if (!isJsonObject(record)) {
|
|
2415
|
+
ctx.badElement("edge", element);
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
if (!present(record, "source") || !present(record, "target")) {
|
|
2419
|
+
ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
try {
|
|
2423
|
+
const u = ctx.coerceId(record.source, `${element}.source`);
|
|
2424
|
+
const v = ctx.coerceId(record.target, `${element}.target`);
|
|
2425
|
+
if (u === null || v === null) {
|
|
2426
|
+
ctx.countSkipped("edge");
|
|
2427
|
+
return;
|
|
2353
2428
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2429
|
+
const kind = graphologyEdgeKind(ctx, reading, record, element);
|
|
2430
|
+
const attributes = graphologyEdgeAttributes(ctx, record, element);
|
|
2431
|
+
const idValue = ctx.edgeIdValue(reading.ids, record.key);
|
|
2432
|
+
const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(attributes), element);
|
|
2433
|
+
ctx.setEdgeId(reading.ids, edge, idValue);
|
|
2434
|
+
ctx.writeNested(ctx.edges, edge, record, attributes, GRAPHOLOGY_EDGE_KEYS, ctx.options.weightFrom, element);
|
|
2435
|
+
if (reading.allowSelfLoops === false && u === v) {
|
|
2436
|
+
reading.violations.selfLoops++;
|
|
2357
2437
|
}
|
|
2358
|
-
|
|
2359
|
-
const
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
ctx.countSkipped("edge");
|
|
2363
|
-
continue;
|
|
2364
|
-
}
|
|
2365
|
-
let kind;
|
|
2366
|
-
if (type === "mixed") {
|
|
2367
|
-
kind = flagOf(record.undirected, `${element}.undirected`, false, report) ? "undirected" : "directed";
|
|
2368
|
-
} else {
|
|
2369
|
-
kind = type;
|
|
2370
|
-
if (typeof record.undirected === "boolean" && record.undirected !== (type === "undirected")) {
|
|
2371
|
-
violations.flags++;
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
const { attributes: rawAttributes } = record;
|
|
2375
|
-
if (rawAttributes !== void 0 && rawAttributes !== null && !isJsonObject(rawAttributes)) {
|
|
2376
|
-
report.error(
|
|
2377
|
-
"validation-error",
|
|
2378
|
-
JSON_ISSUE.BAD_VALUE,
|
|
2379
|
-
`${element}: attributes must be an object, found ${describe(rawAttributes)}`,
|
|
2380
|
-
{ element }
|
|
2381
|
-
);
|
|
2382
|
-
}
|
|
2383
|
-
const attributes = isJsonObject(rawAttributes) ? rawAttributes : {};
|
|
2384
|
-
const idValue = ctx.edgeIdValue(ids, record.key);
|
|
2385
|
-
const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(attributes), element);
|
|
2386
|
-
ctx.setEdgeId(ids, edge, idValue);
|
|
2387
|
-
ctx.writeNested(ctx.edges, edge, record, attributes, GRAPHOLOGY_EDGE_KEYS, ctx.options.weightFrom, element);
|
|
2388
|
-
if (allowSelfLoops === false && u === v) {
|
|
2389
|
-
violations.selfLoops++;
|
|
2390
|
-
}
|
|
2391
|
-
if (pairs !== null) {
|
|
2392
|
-
const pair = `${kind} ${pairKey(u, v, kind === "directed")}`;
|
|
2393
|
-
violations.parallels += pairs.has(pair) ? 1 : 0;
|
|
2394
|
-
pairs.add(pair);
|
|
2395
|
-
}
|
|
2396
|
-
} catch (err) {
|
|
2397
|
-
ctx.skip(err, "edge", element);
|
|
2438
|
+
if (reading.pairs !== null) {
|
|
2439
|
+
const pair = `${kind} ${pairKey(u, v, kind === "directed")}`;
|
|
2440
|
+
reading.violations.parallels += reading.pairs.has(pair) ? 1 : 0;
|
|
2441
|
+
reading.pairs.add(pair);
|
|
2398
2442
|
}
|
|
2443
|
+
} catch (err) {
|
|
2444
|
+
ctx.skip(err, "edge", element);
|
|
2399
2445
|
}
|
|
2400
|
-
|
|
2401
|
-
|
|
2446
|
+
}
|
|
2447
|
+
function graphologyEdgeKind(ctx, reading, record, element) {
|
|
2448
|
+
const { type } = reading;
|
|
2449
|
+
if (type === "mixed") {
|
|
2450
|
+
return flagOf(record.undirected, `${element}.undirected`, false, ctx.report) ? "undirected" : "directed";
|
|
2451
|
+
}
|
|
2452
|
+
if (typeof record.undirected === "boolean" && record.undirected !== (type === "undirected")) {
|
|
2453
|
+
reading.violations.flags++;
|
|
2454
|
+
}
|
|
2455
|
+
return type;
|
|
2456
|
+
}
|
|
2457
|
+
function graphologyEdgeAttributes(ctx, record, element) {
|
|
2458
|
+
const { attributes } = record;
|
|
2459
|
+
if (attributes !== void 0 && attributes !== null && !isJsonObject(attributes)) {
|
|
2460
|
+
ctx.report.error(
|
|
2461
|
+
"validation-error",
|
|
2462
|
+
JSON_ISSUE.BAD_VALUE,
|
|
2463
|
+
`${element}: attributes must be an object, found ${describe(attributes)}`,
|
|
2464
|
+
{ element }
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
return isJsonObject(attributes) ? attributes : {};
|
|
2402
2468
|
}
|
|
2403
2469
|
function reportGraphologyViolations(ctx, violations, type) {
|
|
2404
2470
|
const notes = [];
|
|
@@ -2457,23 +2523,7 @@ function importJgf(ctx, root) {
|
|
|
2457
2523
|
);
|
|
2458
2524
|
}
|
|
2459
2525
|
const nodeRecords = Array.isArray(nodesRaw) ? nodesRaw : Object.values(nodesRaw ?? {});
|
|
2460
|
-
|
|
2461
|
-
if (typeof graph.directed === "boolean") {
|
|
2462
|
-
({ directed } = graph);
|
|
2463
|
-
} else if (ctx.explicitDefaultDirected) {
|
|
2464
|
-
directed = ctx.options.defaultDirected;
|
|
2465
|
-
} else {
|
|
2466
|
-
if (graph.directed !== void 0 && graph.directed !== null) {
|
|
2467
|
-
report.warning(
|
|
2468
|
-
"validation-error",
|
|
2469
|
-
JSON_ISSUE.BAD_FLAG,
|
|
2470
|
-
`graph.directed is ${describe(graph.directed)}, not a boolean`,
|
|
2471
|
-
{ element: "graph.directed" }
|
|
2472
|
-
);
|
|
2473
|
-
}
|
|
2474
|
-
const objects = edges.filter((edge) => isJsonObject(edge));
|
|
2475
|
-
directed = objects.length === 0 || !objects.every((edge) => edge.directed === false);
|
|
2476
|
-
}
|
|
2526
|
+
const directed = jgfDirected(ctx, graph, edges);
|
|
2477
2527
|
ctx.setHeader(directed);
|
|
2478
2528
|
ctx.writeGraphDict(graph.metadata, "graph.metadata");
|
|
2479
2529
|
const shape = {
|
|
@@ -2490,44 +2540,73 @@ function importJgf(ctx, root) {
|
|
|
2490
2540
|
);
|
|
2491
2541
|
if (isJsonObject(nodesRaw)) {
|
|
2492
2542
|
for (const key of Object.keys(nodesRaw)) {
|
|
2493
|
-
|
|
2494
|
-
const record = nodesRaw[key];
|
|
2495
|
-
if (record !== null && !isJsonObject(record)) {
|
|
2496
|
-
ctx.badElement("node", element);
|
|
2497
|
-
continue;
|
|
2498
|
-
}
|
|
2499
|
-
const id = ctx.coerceId(key, element);
|
|
2500
|
-
if (id === null) {
|
|
2501
|
-
ctx.countSkipped("node");
|
|
2502
|
-
continue;
|
|
2503
|
-
}
|
|
2504
|
-
if (record !== null && hasKey(record, "id") && record.id !== key) {
|
|
2505
|
-
report.warning(
|
|
2506
|
-
"validation-error",
|
|
2507
|
-
JSON_ISSUE.INCONSISTENT,
|
|
2508
|
-
`${element}: the inner id ${describe(record.id)} differs from the key; the key is the id, the inner one is kept as id${SUFFIX.element}`,
|
|
2509
|
-
{ element }
|
|
2510
|
-
);
|
|
2511
|
-
}
|
|
2512
|
-
pushJgfNode(ctx, id, record ?? {}, labelColumn, element);
|
|
2543
|
+
pushJgfKeyedNode(ctx, key, nodesRaw[key], labelColumn);
|
|
2513
2544
|
}
|
|
2514
2545
|
} else {
|
|
2515
2546
|
for (let i = 0; i < nodeRecords.length; i++) {
|
|
2516
|
-
|
|
2517
|
-
const record = nodeRecords[i];
|
|
2518
|
-
if (!isJsonObject(record)) {
|
|
2519
|
-
ctx.badElement("node", element);
|
|
2520
|
-
continue;
|
|
2521
|
-
}
|
|
2522
|
-
const id = ctx.coerceId(hasKey(record, "id") ? record.id : void 0, element);
|
|
2523
|
-
if (id === null) {
|
|
2524
|
-
ctx.countSkipped("node");
|
|
2525
|
-
continue;
|
|
2526
|
-
}
|
|
2527
|
-
pushJgfNode(ctx, id, record, labelColumn, element);
|
|
2547
|
+
pushJgfListedNode(ctx, nodeRecords[i], labelColumn, `nodes[${i}]`);
|
|
2528
2548
|
}
|
|
2529
2549
|
}
|
|
2530
2550
|
throwIfAborted(ctx.options.signal);
|
|
2551
|
+
const writeJgfEdge = jgfEdgeWriter(ctx, edges, hyperedges);
|
|
2552
|
+
for (let i = 0; i < edges.length; i++) {
|
|
2553
|
+
readJgfEdge(ctx, edges[i], `edges[${i}]`, directed, writeJgfEdge);
|
|
2554
|
+
}
|
|
2555
|
+
importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
|
|
2556
|
+
ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
|
|
2557
|
+
}
|
|
2558
|
+
function jgfDirected(ctx, graph, edges) {
|
|
2559
|
+
if (typeof graph.directed === "boolean") {
|
|
2560
|
+
return graph.directed;
|
|
2561
|
+
}
|
|
2562
|
+
if (ctx.explicitDefaultDirected) {
|
|
2563
|
+
return ctx.options.defaultDirected;
|
|
2564
|
+
}
|
|
2565
|
+
if (graph.directed !== void 0 && graph.directed !== null) {
|
|
2566
|
+
ctx.report.warning(
|
|
2567
|
+
"validation-error",
|
|
2568
|
+
JSON_ISSUE.BAD_FLAG,
|
|
2569
|
+
`graph.directed is ${describe(graph.directed)}, not a boolean`,
|
|
2570
|
+
{ element: "graph.directed" }
|
|
2571
|
+
);
|
|
2572
|
+
}
|
|
2573
|
+
const objects = edges.filter((edge) => isJsonObject(edge));
|
|
2574
|
+
return objects.length === 0 || !objects.every((edge) => edge.directed === false);
|
|
2575
|
+
}
|
|
2576
|
+
function pushJgfKeyedNode(ctx, key, record, labelColumn) {
|
|
2577
|
+
const element = `nodes[${JSON.stringify(key)}]`;
|
|
2578
|
+
if (record !== null && !isJsonObject(record)) {
|
|
2579
|
+
ctx.badElement("node", element);
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
const id = ctx.coerceId(key, element);
|
|
2583
|
+
if (id === null) {
|
|
2584
|
+
ctx.countSkipped("node");
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2587
|
+
if (record !== null && hasKey(record, "id") && record.id !== key) {
|
|
2588
|
+
ctx.report.warning(
|
|
2589
|
+
"validation-error",
|
|
2590
|
+
JSON_ISSUE.INCONSISTENT,
|
|
2591
|
+
`${element}: the inner id ${describe(record.id)} differs from the key; the key is the id, the inner one is kept as id${SUFFIX.element}`,
|
|
2592
|
+
{ element }
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
pushJgfNode(ctx, id, record ?? {}, labelColumn, element);
|
|
2596
|
+
}
|
|
2597
|
+
function pushJgfListedNode(ctx, record, labelColumn, element) {
|
|
2598
|
+
if (!isJsonObject(record)) {
|
|
2599
|
+
ctx.badElement("node", element);
|
|
2600
|
+
return;
|
|
2601
|
+
}
|
|
2602
|
+
const id = ctx.coerceId(hasKey(record, "id") ? record.id : void 0, element);
|
|
2603
|
+
if (id === null) {
|
|
2604
|
+
ctx.countSkipped("node");
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
pushJgfNode(ctx, id, record, labelColumn, element);
|
|
2608
|
+
}
|
|
2609
|
+
function jgfEdgeWriter(ctx, edges, hyperedges) {
|
|
2531
2610
|
const ids = ctx.declareEdgeIds([...edges, ...hyperedges], (edge) => edge.id, "id", false);
|
|
2532
2611
|
const relationColumn = ctx.edges.declareIf(
|
|
2533
2612
|
{ name: "relation", dtype: "string", role: "kind", nullable: true },
|
|
@@ -2537,7 +2616,7 @@ function importJgf(ctx, root) {
|
|
|
2537
2616
|
{ name: "label", dtype: "string", role: "label", nullable: true },
|
|
2538
2617
|
anyHas(edges, "label") || anyHas(hyperedges, "label")
|
|
2539
2618
|
);
|
|
2540
|
-
|
|
2619
|
+
return (record, u, v, kind, element, structural = JGF_EDGE_KEYS) => {
|
|
2541
2620
|
const { metadata } = record;
|
|
2542
2621
|
const dict = isJsonObject(metadata) ? metadata : {};
|
|
2543
2622
|
const idValue = ctx.edgeIdValue(ids, record.id);
|
|
@@ -2546,38 +2625,34 @@ function importJgf(ctx, root) {
|
|
|
2546
2625
|
ctx.writeStringField(ctx.edges, relationColumn, edge, record.relation, "relation", element);
|
|
2547
2626
|
ctx.writeStringField(ctx.edges, edgeLabelColumn, edge, record.label, "label", element);
|
|
2548
2627
|
if (metadata !== void 0 && metadata !== null && !isJsonObject(metadata)) {
|
|
2549
|
-
report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
|
|
2628
|
+
ctx.report.error("validation-error", JSON_ISSUE.BAD_VALUE, `${element}: metadata must be an object`, {
|
|
2550
2629
|
element
|
|
2551
2630
|
});
|
|
2552
2631
|
}
|
|
2553
2632
|
ctx.writeNested(ctx.edges, edge, record, dict, structural, ctx.options.weightFrom, element);
|
|
2554
2633
|
};
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
continue;
|
|
2572
|
-
}
|
|
2573
|
-
const edgeDirected = flagOf(record.directed, `${element}.directed`, directed, report);
|
|
2574
|
-
writeJgfEdge(record, u, v, edgeDirected ? "directed" : "undirected", element);
|
|
2575
|
-
} catch (err) {
|
|
2576
|
-
ctx.skip(err, "edge", element);
|
|
2634
|
+
}
|
|
2635
|
+
function readJgfEdge(ctx, record, element, directed, writeJgfEdge) {
|
|
2636
|
+
if (!isJsonObject(record)) {
|
|
2637
|
+
ctx.badElement("edge", element);
|
|
2638
|
+
return;
|
|
2639
|
+
}
|
|
2640
|
+
if (!present(record, "source") || !present(record, "target")) {
|
|
2641
|
+
ctx.missingEndpoint(element, present(record, "source") ? "target" : "source");
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
try {
|
|
2645
|
+
const u = ctx.coerceId(record.source, `${element}.source`);
|
|
2646
|
+
const v = ctx.coerceId(record.target, `${element}.target`);
|
|
2647
|
+
if (u === null || v === null) {
|
|
2648
|
+
ctx.countSkipped("edge");
|
|
2649
|
+
return;
|
|
2577
2650
|
}
|
|
2651
|
+
const edgeDirected = flagOf(record.directed, `${element}.directed`, directed, ctx.report);
|
|
2652
|
+
writeJgfEdge(record, u, v, edgeDirected ? "directed" : "undirected", element);
|
|
2653
|
+
} catch (err) {
|
|
2654
|
+
ctx.skip(err, "edge", element);
|
|
2578
2655
|
}
|
|
2579
|
-
importHyperedges(ctx, hyperedges, directed, writeJgfEdge);
|
|
2580
|
-
ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
|
|
2581
2656
|
}
|
|
2582
2657
|
function jgfGraphOf(ctx, root) {
|
|
2583
2658
|
const single = isJsonObject(root.graph);
|
|
@@ -2832,49 +2907,34 @@ function distinctMembers(ctx, members, element) {
|
|
|
2832
2907
|
return distinct;
|
|
2833
2908
|
}
|
|
2834
2909
|
function importCytoscape(ctx, root) {
|
|
2835
|
-
const {
|
|
2836
|
-
let elements;
|
|
2837
|
-
let extra;
|
|
2838
|
-
if (Array.isArray(root)) {
|
|
2839
|
-
elements = root;
|
|
2840
|
-
} else if (isJsonObject(root)) {
|
|
2841
|
-
({ elements } = root);
|
|
2842
|
-
ctx.writeGraphDict(root.data, "data");
|
|
2843
|
-
const rest = {};
|
|
2844
|
-
for (const key of Object.keys(root)) {
|
|
2845
|
-
if (key !== "elements" && key !== "data") {
|
|
2846
|
-
rest[key] = root[key];
|
|
2847
|
-
}
|
|
2848
|
-
}
|
|
2849
|
-
if (Object.keys(rest).length > 0) {
|
|
2850
|
-
extra = rest;
|
|
2851
|
-
}
|
|
2852
|
-
} else {
|
|
2853
|
-
report.fail(JSON_ISSUE.SHAPE, `a Cytoscape document must be an object or an array, found ${describe(root)}`);
|
|
2854
|
-
}
|
|
2910
|
+
const { elements, extra } = cytoscapeRoot(ctx, root);
|
|
2855
2911
|
const { nodes, edges } = cytoscapeSections(ctx, elements);
|
|
2856
2912
|
ctx.setHeader(ctx.defaultDirected("cytoscape"));
|
|
2857
2913
|
ctx.reportNodeIdFrom("cytoscape", "data.id");
|
|
2858
2914
|
ctx.sink.reserve(nodes.length, edges.length);
|
|
2859
2915
|
const dataHas = (items, key) => items.some((item) => isJsonObject(item) && isJsonObject(item.data) && item.data[key] !== void 0);
|
|
2860
|
-
const
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2916
|
+
const reading = {
|
|
2917
|
+
positionColumn: ctx.nodes.declareIf(
|
|
2918
|
+
{
|
|
2919
|
+
name: POSITION_COLUMN,
|
|
2920
|
+
dtype: "f64",
|
|
2921
|
+
components: 3,
|
|
2922
|
+
role: "position",
|
|
2923
|
+
mutable: true,
|
|
2924
|
+
nullable: true,
|
|
2925
|
+
// 3D layouts written by Cytoscape-compatible tools carry a z
|
|
2926
|
+
extra: { sourceDims: nodes.some(hasPositionZ) ? 3 : 2, units: "file" },
|
|
2927
|
+
origin: { format: "json", namespace: "cytoscape" }
|
|
2928
|
+
},
|
|
2929
|
+
anyHas(nodes, "position")
|
|
2930
|
+
),
|
|
2931
|
+
classesColumn: ctx.nodes.declareIf(
|
|
2932
|
+
{ name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
|
|
2933
|
+
anyHas(nodes, "classes")
|
|
2934
|
+
),
|
|
2935
|
+
parents: [],
|
|
2936
|
+
point: [0, 0, 0]
|
|
2937
|
+
};
|
|
2878
2938
|
const parentColumn = ctx.nodes.declareIf(
|
|
2879
2939
|
{ name: PARENT_COLUMN, dtype: "u32", role: "parent", refersTo: "node", nullable: true },
|
|
2880
2940
|
dataHas(nodes, "parent")
|
|
@@ -2883,77 +2943,104 @@ function importCytoscape(ctx, root) {
|
|
|
2883
2943
|
{ name: CLASSES_COLUMN, dtype: "list", itemDtype: "string", role: "classes", nullable: true },
|
|
2884
2944
|
anyHas(edges, "classes")
|
|
2885
2945
|
);
|
|
2886
|
-
const parents = [];
|
|
2887
|
-
const point = [0, 0, 0];
|
|
2888
2946
|
for (let i = 0; i < nodes.length; i++) {
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2947
|
+
readCytoscapeNode(ctx, reading, nodes[i], `nodes[${i}]`);
|
|
2948
|
+
}
|
|
2949
|
+
resolveCytoscapeParents(ctx, reading.parents, parentColumn);
|
|
2950
|
+
throwIfAborted(ctx.options.signal);
|
|
2951
|
+
importCytoscapeEdges(ctx, edges, edgeClassesColumn);
|
|
2952
|
+
ctx.setMeta({ dialect: "cytoscape", cytoscape: extra }, ctx.weightOriginPatch());
|
|
2953
|
+
}
|
|
2954
|
+
function cytoscapeRoot(ctx, root) {
|
|
2955
|
+
if (Array.isArray(root)) {
|
|
2956
|
+
return { elements: root };
|
|
2957
|
+
}
|
|
2958
|
+
if (!isJsonObject(root)) {
|
|
2959
|
+
ctx.report.fail(
|
|
2960
|
+
JSON_ISSUE.SHAPE,
|
|
2961
|
+
`a Cytoscape document must be an object or an array, found ${describe(root)}`
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
ctx.writeGraphDict(root.data, "data");
|
|
2965
|
+
const rest = {};
|
|
2966
|
+
for (const key of Object.keys(root)) {
|
|
2967
|
+
if (key !== "elements" && key !== "data") {
|
|
2968
|
+
rest[key] = root[key];
|
|
2894
2969
|
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2970
|
+
}
|
|
2971
|
+
return Object.keys(rest).length > 0 ? { elements: root.elements, extra: rest } : { elements: root.elements };
|
|
2972
|
+
}
|
|
2973
|
+
function readCytoscapeNode(ctx, reading, record, element) {
|
|
2974
|
+
const { report } = ctx;
|
|
2975
|
+
if (!isJsonObject(record) || !isJsonObject(record.data)) {
|
|
2976
|
+
ctx.badElement("node", element, "an element with a data object");
|
|
2977
|
+
return;
|
|
2978
|
+
}
|
|
2979
|
+
const { data } = record;
|
|
2980
|
+
const id = ctx.coerceId(hasKey(data, "id") ? data.id : void 0, element);
|
|
2981
|
+
if (id === null) {
|
|
2982
|
+
ctx.countSkipped("node");
|
|
2983
|
+
return;
|
|
2984
|
+
}
|
|
2985
|
+
const index = ctx.pushNode(id, element);
|
|
2986
|
+
if (index < 0) {
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
if (present(data, "source") && present(data, "target")) {
|
|
2990
|
+
report.warning(
|
|
2991
|
+
"validation-error",
|
|
2992
|
+
JSON_ISSUE.INCONSISTENT,
|
|
2993
|
+
`${element} has data.source and data.target, the shape of an edge, but its section or group says node; read as a node`,
|
|
2994
|
+
{ element }
|
|
2995
|
+
);
|
|
2996
|
+
}
|
|
2997
|
+
try {
|
|
2998
|
+
writeCytoscapeData(ctx, reading, index, data, element);
|
|
2999
|
+
writeCytoscapePosition$1(ctx, reading, index, record.position, element);
|
|
3000
|
+
writeClasses(ctx, ctx.nodes, reading.classesColumn, index, record.classes, element);
|
|
3001
|
+
writeElementKeys(ctx.nodes, index, record, element);
|
|
3002
|
+
} catch (err) {
|
|
3003
|
+
report.recordError(err, { element: String(id) });
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
function writeCytoscapeData(ctx, reading, index, data, element) {
|
|
3007
|
+
for (const key of Object.keys(data)) {
|
|
3008
|
+
if (key === "id") {
|
|
2899
3009
|
continue;
|
|
2900
3010
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
3011
|
+
if (key !== "parent") {
|
|
3012
|
+
ctx.nodes.write(index, key, data[key], SUFFIX.data, element);
|
|
2903
3013
|
continue;
|
|
2904
3014
|
}
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
JSON_ISSUE.INCONSISTENT,
|
|
2909
|
-
`${element} has data.source and data.target, the shape of an edge, but its section or group says node; read as a node`,
|
|
2910
|
-
{ element }
|
|
2911
|
-
);
|
|
3015
|
+
const raw = data.parent;
|
|
3016
|
+
if (raw === void 0 || raw === null) {
|
|
3017
|
+
continue;
|
|
2912
3018
|
}
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
continue;
|
|
2917
|
-
}
|
|
2918
|
-
if (key === "parent") {
|
|
2919
|
-
const raw = data.parent;
|
|
2920
|
-
if (raw !== void 0 && raw !== null) {
|
|
2921
|
-
const parent = ctx.coerceId(raw, `${element}.data.parent`);
|
|
2922
|
-
if (parent !== null) {
|
|
2923
|
-
parents.push({ index, parent, element });
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
|
-
continue;
|
|
2927
|
-
}
|
|
2928
|
-
ctx.nodes.write(index, key, data[key], SUFFIX.data, element);
|
|
2929
|
-
}
|
|
2930
|
-
const { position } = record;
|
|
2931
|
-
if (position !== void 0 && position !== null) {
|
|
2932
|
-
const z = isJsonObject(position) ? position.z ?? 0 : 0;
|
|
2933
|
-
if (isJsonObject(position) && isCoordinate(position.x) && isCoordinate(position.y) && isCoordinate(z)) {
|
|
2934
|
-
point[0] = position.x;
|
|
2935
|
-
point[1] = flipY(position.y);
|
|
2936
|
-
point[2] = z;
|
|
2937
|
-
ctx.nodes.set(positionColumn, index, point);
|
|
2938
|
-
} else {
|
|
2939
|
-
report.error(
|
|
2940
|
-
"validation-error",
|
|
2941
|
-
JSON_ISSUE.BAD_VALUE,
|
|
2942
|
-
`${element}: position must be an object with numeric x and y (and z) that are finite numbers`,
|
|
2943
|
-
{ element }
|
|
2944
|
-
);
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
writeClasses(ctx, ctx.nodes, classesColumn, index, record.classes, element);
|
|
2948
|
-
writeElementKeys(ctx.nodes, index, record, element);
|
|
2949
|
-
} catch (err) {
|
|
2950
|
-
report.recordError(err, { element: String(id) });
|
|
3019
|
+
const parent = ctx.coerceId(raw, `${element}.data.parent`);
|
|
3020
|
+
if (parent !== null) {
|
|
3021
|
+
reading.parents.push({ index, parent, element });
|
|
2951
3022
|
}
|
|
2952
3023
|
}
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
3024
|
+
}
|
|
3025
|
+
function writeCytoscapePosition$1(ctx, reading, index, position, element) {
|
|
3026
|
+
if (position === void 0 || position === null) {
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
const z = isJsonObject(position) ? position.z ?? 0 : 0;
|
|
3030
|
+
if (isJsonObject(position) && isCoordinate(position.x) && isCoordinate(position.y) && isCoordinate(z)) {
|
|
3031
|
+
const { point } = reading;
|
|
3032
|
+
point[0] = position.x;
|
|
3033
|
+
point[1] = flipY(position.y);
|
|
3034
|
+
point[2] = z;
|
|
3035
|
+
ctx.nodes.set(reading.positionColumn, index, point);
|
|
3036
|
+
} else {
|
|
3037
|
+
ctx.report.error(
|
|
3038
|
+
"validation-error",
|
|
3039
|
+
JSON_ISSUE.BAD_VALUE,
|
|
3040
|
+
`${element}: position must be an object with numeric x and y (and z) that are finite numbers`,
|
|
3041
|
+
{ element }
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
2957
3044
|
}
|
|
2958
3045
|
function resolveCytoscapeParents(ctx, parents, parentColumn) {
|
|
2959
3046
|
const { report } = ctx;
|
|
@@ -3028,27 +3115,31 @@ function importCytoscapeEdges(ctx, edges, edgeClassesColumn) {
|
|
|
3028
3115
|
ctx.missingEndpoint(element, `data.${present(data, "source") ? "target" : "source"}`);
|
|
3029
3116
|
continue;
|
|
3030
3117
|
}
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
ctx.
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3118
|
+
importCytoscapeEdge(ctx, { ids, kind, edgeClassesColumn }, record, data, element);
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
function importCytoscapeEdge(ctx, shared, record, data, element) {
|
|
3122
|
+
const { ids, kind, edgeClassesColumn } = shared;
|
|
3123
|
+
try {
|
|
3124
|
+
const u = ctx.coerceId(data.source, `${element}.data.source`);
|
|
3125
|
+
const v = ctx.coerceId(data.target, `${element}.data.target`);
|
|
3126
|
+
if (u === null || v === null) {
|
|
3127
|
+
ctx.countSkipped("edge");
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
const idValue = ctx.edgeIdValue(ids, data.id);
|
|
3131
|
+
const edge = ctx.pushEdge(u, v, kind, ctx.weightOf(data), element);
|
|
3132
|
+
ctx.setEdgeId(ids, edge, idValue);
|
|
3133
|
+
const { weightFrom } = ctx.options;
|
|
3134
|
+
for (const key of Object.keys(data)) {
|
|
3135
|
+
if (key !== "id" && key !== "source" && key !== "target" && key !== weightFrom) {
|
|
3136
|
+
ctx.edges.write(edge, key, data[key], SUFFIX.data, element);
|
|
3046
3137
|
}
|
|
3047
|
-
writeClasses(ctx, ctx.edges, edgeClassesColumn, edge, record.classes, element);
|
|
3048
|
-
writeElementKeys(ctx.edges, edge, record, element);
|
|
3049
|
-
} catch (err) {
|
|
3050
|
-
ctx.skip(err, "edge", element);
|
|
3051
3138
|
}
|
|
3139
|
+
writeClasses(ctx, ctx.edges, edgeClassesColumn, edge, record.classes, element);
|
|
3140
|
+
writeElementKeys(ctx.edges, edge, record, element);
|
|
3141
|
+
} catch (err) {
|
|
3142
|
+
ctx.skip(err, "edge", element);
|
|
3052
3143
|
}
|
|
3053
3144
|
}
|
|
3054
3145
|
function cytoscapeSections(ctx, elements) {
|
|
@@ -3566,21 +3657,7 @@ function writeNode(ctx, columns, vocabulary, record, row, element) {
|
|
|
3566
3657
|
}
|
|
3567
3658
|
function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
|
|
3568
3659
|
const path = `${element}.meta`;
|
|
3569
|
-
|
|
3570
|
-
if (isJsonObject(definition)) {
|
|
3571
|
-
const xrefs2 = strings$1(ctx, definition.xrefs, `${path}.definition.xrefs`);
|
|
3572
|
-
if (typeof definition.val === "string") {
|
|
3573
|
-
columns.node("def", row, definition.val);
|
|
3574
|
-
columns.node("def.xrefs", row, xrefs2);
|
|
3575
|
-
} else {
|
|
3576
|
-
badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
|
|
3577
|
-
}
|
|
3578
|
-
if (definition.meta !== void 0) {
|
|
3579
|
-
unrecognized["meta.definition.meta"] = definition.meta;
|
|
3580
|
-
}
|
|
3581
|
-
} else if (definition !== void 0 && definition !== null) {
|
|
3582
|
-
badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
|
|
3583
|
-
}
|
|
3660
|
+
writeDefinition(ctx, columns, meta.definition, row, unrecognized, path);
|
|
3584
3661
|
const comments = strings$1(ctx, meta.comments, `${path}.comments`);
|
|
3585
3662
|
if (comments.length > 0) {
|
|
3586
3663
|
columns.node("comment", row, comments.join("\n"));
|
|
@@ -3609,6 +3686,22 @@ function writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element) {
|
|
|
3609
3686
|
}
|
|
3610
3687
|
}
|
|
3611
3688
|
}
|
|
3689
|
+
function writeDefinition(ctx, columns, definition, row, unrecognized, path) {
|
|
3690
|
+
if (isJsonObject(definition)) {
|
|
3691
|
+
const xrefs = strings$1(ctx, definition.xrefs, `${path}.definition.xrefs`);
|
|
3692
|
+
if (typeof definition.val === "string") {
|
|
3693
|
+
columns.node("def", row, definition.val);
|
|
3694
|
+
columns.node("def.xrefs", row, xrefs);
|
|
3695
|
+
} else {
|
|
3696
|
+
badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
|
|
3697
|
+
}
|
|
3698
|
+
if (definition.meta !== void 0) {
|
|
3699
|
+
unrecognized["meta.definition.meta"] = definition.meta;
|
|
3700
|
+
}
|
|
3701
|
+
} else if (definition !== void 0 && definition !== null) {
|
|
3702
|
+
badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3612
3705
|
function synonymsOf(ctx, vocabulary, value, path) {
|
|
3613
3706
|
if (value === void 0 || value === null) {
|
|
3614
3707
|
return [];
|
|
@@ -5782,7 +5875,6 @@ function* writeCytoscape(snapshot, p) {
|
|
|
5782
5875
|
const c = { w: new JsonWriter(resolved.indent), ids: snapshot.ids, nonfinite: { count: 0 } };
|
|
5783
5876
|
const { w } = c;
|
|
5784
5877
|
const parentSlots = /* @__PURE__ */ new Set(["parent"]);
|
|
5785
|
-
const positionSlots = /* @__PURE__ */ new Set(["cytoscapePosition"]);
|
|
5786
5878
|
w.open("{");
|
|
5787
5879
|
w.key("elements");
|
|
5788
5880
|
w.open("{");
|
|
@@ -5798,17 +5890,7 @@ function* writeCytoscape(snapshot, p) {
|
|
|
5798
5890
|
writeSlots(c, p.nodes, i, parentSlots);
|
|
5799
5891
|
writeSlots(c, p.nodes, i, ATTRIBUTE_SLOTS);
|
|
5800
5892
|
w.close("}");
|
|
5801
|
-
|
|
5802
|
-
if (positionSlots.has(item.slot) && item.column.isSet(i)) {
|
|
5803
|
-
const value = item.column.value(i);
|
|
5804
|
-
const f32 = item.column.dtype === "f32";
|
|
5805
|
-
w.key("position");
|
|
5806
|
-
w.open("{");
|
|
5807
|
-
w.member("x", numberText(value[0], f32, c.nonfinite));
|
|
5808
|
-
w.member("y", numberText(flipY(value[1]), f32, c.nonfinite));
|
|
5809
|
-
w.close("}");
|
|
5810
|
-
}
|
|
5811
|
-
}
|
|
5893
|
+
writeCytoscapePosition(c, p.nodes, i);
|
|
5812
5894
|
writeSlots(c, p.nodes, i, ELEMENT_SLOTS);
|
|
5813
5895
|
w.close("}");
|
|
5814
5896
|
yield w.take();
|
|
@@ -5845,17 +5927,34 @@ function* writeCytoscape(snapshot, p) {
|
|
|
5845
5927
|
w.key("data");
|
|
5846
5928
|
writeGraphObject(c, p);
|
|
5847
5929
|
}
|
|
5848
|
-
|
|
5849
|
-
if (extra !== void 0) {
|
|
5850
|
-
for (const key of Object.keys(extra)) {
|
|
5851
|
-
if (key !== "elements" && key !== "data") {
|
|
5852
|
-
w.member(key, valueText(extra[key], false, c.nonfinite));
|
|
5853
|
-
}
|
|
5854
|
-
}
|
|
5855
|
-
}
|
|
5930
|
+
writeCytoscapeExtra(c, resolved.shape.cytoscape);
|
|
5856
5931
|
w.close("}");
|
|
5857
5932
|
yield w.take();
|
|
5858
5933
|
}
|
|
5934
|
+
function writeCytoscapePosition(c, items, i) {
|
|
5935
|
+
const { w } = c;
|
|
5936
|
+
for (const item of items) {
|
|
5937
|
+
if (item.slot === "cytoscapePosition" && item.column.isSet(i)) {
|
|
5938
|
+
const value = item.column.value(i);
|
|
5939
|
+
const f32 = item.column.dtype === "f32";
|
|
5940
|
+
w.key("position");
|
|
5941
|
+
w.open("{");
|
|
5942
|
+
w.member("x", numberText(value[0], f32, c.nonfinite));
|
|
5943
|
+
w.member("y", numberText(flipY(value[1]), f32, c.nonfinite));
|
|
5944
|
+
w.close("}");
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5948
|
+
function writeCytoscapeExtra(c, extra) {
|
|
5949
|
+
if (extra === void 0) {
|
|
5950
|
+
return;
|
|
5951
|
+
}
|
|
5952
|
+
for (const key of Object.keys(extra)) {
|
|
5953
|
+
if (key !== "elements" && key !== "data") {
|
|
5954
|
+
c.w.member(key, valueText(extra[key], false, c.nonfinite));
|
|
5955
|
+
}
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5859
5958
|
function edgeIdGenerator(snapshot, p) {
|
|
5860
5959
|
const used = /* @__PURE__ */ new Set();
|
|
5861
5960
|
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
@@ -5946,4 +6045,4 @@ export {
|
|
|
5946
6045
|
rankFormats as r,
|
|
5947
6046
|
sniffFormat as s
|
|
5948
6047
|
};
|
|
5949
|
-
//# sourceMappingURL=exporter-
|
|
6048
|
+
//# sourceMappingURL=exporter-CpRyHZ3H.js.map
|