@graphty/graph-io 0.3.17 → 0.3.19
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/LICENSE +1 -1
- package/README.md +64 -3
- package/dist/chunks/{escape-scjHxjpr.js → escape-CWExcecC.js} +3 -2
- package/dist/chunks/{escape-scjHxjpr.js.map → escape-CWExcecC.js.map} +1 -1
- package/dist/chunks/exporter-CbMZyVt-.js +735 -0
- package/dist/chunks/exporter-CbMZyVt-.js.map +1 -0
- package/dist/chunks/importer-BAP4PrxR.js +2194 -0
- package/dist/chunks/importer-BAP4PrxR.js.map +1 -0
- package/dist/chunks/{importer-Xg07gk7p.js → importer-BNFuV1-K.js} +5 -3
- package/dist/chunks/{importer-Xg07gk7p.js.map → importer-BNFuV1-K.js.map} +1 -1
- package/dist/chunks/{importer-BmOl9gLW.js → importer-BVGtU1NA.js} +5 -3
- package/dist/chunks/{importer-BmOl9gLW.js.map → importer-BVGtU1NA.js.map} +1 -1
- package/dist/chunks/{importer-ruMWWvVs.js → importer-BW-Ft2ps.js} +5 -3
- package/dist/chunks/{importer-ruMWWvVs.js.map → importer-BW-Ft2ps.js.map} +1 -1
- package/dist/chunks/{importer-B6rKRxzv.js → importer-Bm1_5vPS.js} +781 -104
- package/dist/chunks/importer-Bm1_5vPS.js.map +1 -0
- package/dist/chunks/importer-ByPGO-09.js +1614 -0
- package/dist/chunks/importer-ByPGO-09.js.map +1 -0
- package/dist/chunks/importer-DOepkgnG.js +1713 -0
- package/dist/chunks/importer-DOepkgnG.js.map +1 -0
- package/dist/chunks/json-elements-CZY1wiZh.js +779 -0
- package/dist/chunks/json-elements-CZY1wiZh.js.map +1 -0
- package/dist/chunks/ontology-BnrJ4I98.js +113 -0
- package/dist/chunks/ontology-BnrJ4I98.js.map +1 -0
- package/dist/chunks/{records-DSpbTE5s.js → records-BzNicMsf.js} +2 -2
- package/dist/chunks/{records-DSpbTE5s.js.map → records-BzNicMsf.js.map} +1 -1
- package/dist/chunks/{writer-DHHfHn11.js → report-BcWboivV.js} +106 -928
- package/dist/chunks/report-BcWboivV.js.map +1 -0
- package/dist/chunks/weights-CwISIpCP.js +176 -0
- package/dist/chunks/weights-CwISIpCP.js.map +1 -0
- package/dist/chunks/writer-DQiKgQJc.js +656 -0
- package/dist/chunks/writer-DQiKgQJc.js.map +1 -0
- package/dist/csv.js +5 -3
- package/dist/csv.js.map +1 -1
- package/dist/cx.d.ts +1 -0
- package/dist/cx.js +6 -0
- package/dist/cx.js.map +1 -0
- package/dist/cx2.d.ts +1 -0
- package/dist/cx2.js +10 -0
- package/dist/cx2.js.map +1 -0
- package/dist/dot.js +1 -1
- package/dist/gexf.js +15 -3
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +5 -3
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +158 -383
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +1 -1
- package/dist/json.js +1 -1
- package/dist/neo4j.js +5 -3
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.d.ts +1 -0
- package/dist/obo.js +6 -0
- package/dist/obo.js.map +1 -0
- package/dist/pajek.js +1 -1
- package/dist/src/common/json-elements.d.ts +286 -0
- package/dist/src/common/json-elements.d.ts.map +1 -0
- package/dist/src/common/json-elements.js +926 -0
- package/dist/src/common/json-elements.js.map +1 -0
- package/dist/src/common/ontology.d.ts +59 -0
- package/dist/src/common/ontology.d.ts.map +1 -0
- package/dist/src/common/ontology.js +147 -0
- package/dist/src/common/ontology.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts +133 -0
- package/dist/src/formats/cx/importer.d.ts.map +1 -0
- package/dist/src/formats/cx/importer.js +2220 -0
- package/dist/src/formats/cx/importer.js.map +1 -0
- package/dist/src/formats/cx/index.d.ts +7 -0
- package/dist/src/formats/cx/index.d.ts.map +1 -0
- package/dist/src/formats/cx/index.js +7 -0
- package/dist/src/formats/cx/index.js.map +1 -0
- package/dist/src/formats/cx2/exporter.d.ts +59 -0
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -0
- package/dist/src/formats/cx2/exporter.js +864 -0
- package/dist/src/formats/cx2/exporter.js.map +1 -0
- package/dist/src/formats/cx2/importer.d.ts +169 -0
- package/dist/src/formats/cx2/importer.d.ts.map +1 -0
- package/dist/src/formats/cx2/importer.js +1652 -0
- package/dist/src/formats/cx2/importer.js.map +1 -0
- package/dist/src/formats/cx2/index.d.ts +7 -0
- package/dist/src/formats/cx2/index.d.ts.map +1 -0
- package/dist/src/formats/cx2/index.js +7 -0
- package/dist/src/formats/cx2/index.js.map +1 -0
- package/dist/src/formats/gexf/exporter.d.ts +2 -0
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +6 -0
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +2 -4
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +2 -4
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +1 -1
- package/dist/src/formats/gexf/index.js +2 -2
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gml/exporter.js +1 -1
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +8 -6
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +26 -3
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +324 -7
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +159 -126
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/obographs.d.ts +21 -0
- package/dist/src/formats/json/obographs.d.ts.map +1 -0
- package/dist/src/formats/json/obographs.js +476 -0
- package/dist/src/formats/json/obographs.js.map +1 -0
- package/dist/src/formats/obo/importer.d.ts +90 -0
- package/dist/src/formats/obo/importer.d.ts.map +1 -0
- package/dist/src/formats/obo/importer.js +1248 -0
- package/dist/src/formats/obo/importer.js.map +1 -0
- package/dist/src/formats/obo/index.d.ts +7 -0
- package/dist/src/formats/obo/index.d.ts.map +1 -0
- package/dist/src/formats/obo/index.js +7 -0
- package/dist/src/formats/obo/index.js.map +1 -0
- package/dist/src/formats/obo/syntax.d.ts +121 -0
- package/dist/src/formats/obo/syntax.d.ts.map +1 -0
- package/dist/src/formats/obo/syntax.js +424 -0
- package/dist/src/formats/obo/syntax.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +8 -1
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sniff.d.ts +1 -1
- package/dist/src/sniff.d.ts.map +1 -1
- package/dist/src/sniff.js +25 -3
- package/dist/src/sniff.js.map +1 -1
- package/package.json +16 -1
- package/src/common/json-elements.ts +1147 -0
- package/src/common/ontology.ts +169 -0
- package/src/formats/cx/importer.ts +2733 -0
- package/src/formats/cx/index.ts +7 -0
- package/src/formats/cx2/exporter.ts +1036 -0
- package/src/formats/cx2/importer.ts +2187 -0
- package/src/formats/cx2/index.ts +7 -0
- package/src/formats/gexf/exporter.ts +11 -0
- package/src/formats/gexf/importer.ts +2 -2
- package/src/formats/gexf/index.ts +1 -1
- package/src/formats/gml/exporter.ts +1 -1
- package/src/formats/json/dialect.ts +37 -7
- package/src/formats/json/importer.ts +210 -132
- package/src/formats/json/obographs.ts +563 -0
- package/src/formats/obo/importer.ts +1695 -0
- package/src/formats/obo/index.ts +7 -0
- package/src/formats/obo/syntax.ts +466 -0
- package/src/index.ts +11 -0
- package/src/registry.ts +8 -1
- package/src/sniff.ts +48 -5
- package/dist/chunks/importer-B6rKRxzv.js.map +0 -1
- package/dist/chunks/writer-DHHfHn11.js.map +0 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
|
|
2
|
-
import {
|
|
2
|
+
import { aB as resolveExportOptions, ax as pairFolding, ar as declareResolved, af as UNKNOWN_ENCODING_CODE, r as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, U as OPTION_IGNORED_CODE, a2 as SINK_OPTION_CODE, H as HYPEREDGE_CODE, ac as TOO_LARGE_CODE, D as DANGLING_REFERENCE_CODE, A as AMBIGUOUS_GRAPH_NAME_CODE, G as GRAPH_NOT_FOUND_CODE, O as MULTIPLE_GRAPHS_CODE, u as ID_MERGED_CODE, m as DUPLICATE_EDGE_ID_CODE, o as DUPLICATE_NODE_CODE, ag as UNKNOWN_PARENT_CODE, d as BAD_VALUE_CODE, M as MISSING_ENDPOINT_CODE, K as MISSING_ID_CODE, a8 as SYNTAX_CODE, q as EMPTY_INPUT_CODE, aC as resolveImportOptions, I as ImportReportBuilder, ay as readText, aD as textChunks, az as reportSinkOptions, aA as reportUnusedOptions, t as throwIfAborted, F as IdCoercer, p as DirectionResolver, aE as uniqueColumnName, an as chooseGraph } from "./report-BcWboivV.js";
|
|
3
|
+
import { c as capabilities, L as LOSS, j as joinText, e as encodeChunks, a as checkCapabilities, g as countMixedEdges } from "./writer-DQiKgQJc.js";
|
|
4
|
+
import { e as explicitWeights, a as formatF32, b as formatF64, w as weightFromValue } from "./weights-CwISIpCP.js";
|
|
5
|
+
import { M as MAYBE_UNSAFE_INTEGER, e as rewriteNumbers, g as reviveNonstandard } from "./json-elements-CZY1wiZh.js";
|
|
6
|
+
import { a as OBOGRAPHS_PREDICATE_TAGS, c as compactOboIri, o as oboColumnDecl, P as PLACEHOLDER_COLUMN, s as synonymScopeOf, O as OBO_NODE_COLUMNS } from "./ontology-BnrJ4I98.js";
|
|
3
7
|
const JSON_DIALECTS = Object.freeze([
|
|
4
8
|
"node-link",
|
|
5
9
|
"d3",
|
|
@@ -11,7 +15,8 @@ const JSON_DIALECTS = Object.freeze([
|
|
|
11
15
|
const JSON_IMPORT_DIALECTS = Object.freeze([
|
|
12
16
|
...JSON_DIALECTS,
|
|
13
17
|
"adjacency",
|
|
14
|
-
"tree"
|
|
18
|
+
"tree",
|
|
19
|
+
"obographs"
|
|
15
20
|
]);
|
|
16
21
|
const META_KEY = "json";
|
|
17
22
|
function isJsonObject(value) {
|
|
@@ -41,7 +46,7 @@ function sniffJsonDialect(root) {
|
|
|
41
46
|
return "jgf";
|
|
42
47
|
}
|
|
43
48
|
if (Array.isArray(root.graphs)) {
|
|
44
|
-
return "jgf";
|
|
49
|
+
return isOboGraph(firstJsonObject(root.graphs)) ? "obographs" : "jgf";
|
|
45
50
|
}
|
|
46
51
|
if (!hasKey(root, "edges") && !hasKey(root, "links")) {
|
|
47
52
|
if (hasKey(root, "nodes") && hasKey(root, "adjacency")) {
|
|
@@ -70,6 +75,15 @@ function sniffJsonDialect(root) {
|
|
|
70
75
|
const bare = !hasKey(root, "directed") && !hasKey(root, "multigraph") && !hasKey(root, "graph");
|
|
71
76
|
return bare && hasKey(root, "links") ? "d3" : "node-link";
|
|
72
77
|
}
|
|
78
|
+
const OBOGRAPHS_NODE_TYPES = /* @__PURE__ */ new Set(["CLASS", "INDIVIDUAL", "PROPERTY"]);
|
|
79
|
+
function isOboGraph(graph) {
|
|
80
|
+
if (graph === null) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const isEdge = (e) => isJsonObject(e) && (hasKey(e, "obj") && (hasKey(e, "sub") || hasKey(e, "subj")) || hasKey(e, "pred"));
|
|
84
|
+
const isNode = (n) => isJsonObject(n) && (hasKey(n, "lbl") || hasKey(n, "meta") || OBOGRAPHS_NODE_TYPES.has(n.type));
|
|
85
|
+
return Array.isArray(graph.edges) && graph.edges.some(isEdge) || Array.isArray(graph.nodes) && graph.nodes.some(isNode);
|
|
86
|
+
}
|
|
73
87
|
function firstJsonObject(value) {
|
|
74
88
|
if (!Array.isArray(value)) {
|
|
75
89
|
return null;
|
|
@@ -107,7 +121,9 @@ const DIALECT_DEFAULT_DIRECTED = Object.freeze({
|
|
|
107
121
|
vis: false,
|
|
108
122
|
// networkx adjacency_data declares `directed`; tree_graph always builds a DiGraph
|
|
109
123
|
adjacency: false,
|
|
110
|
-
tree: true
|
|
124
|
+
tree: true,
|
|
125
|
+
// OBO Graphs edges point from the subject (child) to the object (parent)
|
|
126
|
+
obographs: true
|
|
111
127
|
});
|
|
112
128
|
const JSON_DTYPES = Object.freeze(["f64", "i32", "bool", "string"]);
|
|
113
129
|
const COMMON = {
|
|
@@ -1356,6 +1372,643 @@ const jsonExporter = Object.freeze({
|
|
|
1356
1372
|
function jsonCapabilities(dialect) {
|
|
1357
1373
|
return dialectCapabilities(dialect);
|
|
1358
1374
|
}
|
|
1375
|
+
const GRAPH_FORMATS = Object.freeze([
|
|
1376
|
+
"json",
|
|
1377
|
+
"graphml",
|
|
1378
|
+
"gexf",
|
|
1379
|
+
"csv",
|
|
1380
|
+
"gml",
|
|
1381
|
+
"dot",
|
|
1382
|
+
"pajek",
|
|
1383
|
+
"neo4j",
|
|
1384
|
+
"cx2",
|
|
1385
|
+
"cx",
|
|
1386
|
+
"obo"
|
|
1387
|
+
]);
|
|
1388
|
+
const SNIFF_HEAD_BYTES = 8192;
|
|
1389
|
+
function extensionOf(filename) {
|
|
1390
|
+
const base = filename.slice(Math.max(filename.lastIndexOf("/"), filename.lastIndexOf("\\")) + 1);
|
|
1391
|
+
const dot = base.lastIndexOf(".");
|
|
1392
|
+
if (dot <= 0 || dot === base.length - 1) {
|
|
1393
|
+
return null;
|
|
1394
|
+
}
|
|
1395
|
+
return base.slice(dot).toLowerCase();
|
|
1396
|
+
}
|
|
1397
|
+
function normalizeMimeType(mimeType) {
|
|
1398
|
+
const semicolon = mimeType.indexOf(";");
|
|
1399
|
+
return (semicolon < 0 ? mimeType : mimeType.slice(0, semicolon)).trim().toLowerCase();
|
|
1400
|
+
}
|
|
1401
|
+
function headBytes(head) {
|
|
1402
|
+
if (typeof head === "string") {
|
|
1403
|
+
return new TextEncoder().encode(head.slice(0, SNIFF_HEAD_BYTES)).subarray(0, SNIFF_HEAD_BYTES);
|
|
1404
|
+
}
|
|
1405
|
+
if (head.byteLength >= 2 && (head[0] === 255 && head[1] === 254 || head[0] === 254 && head[1] === 255)) {
|
|
1406
|
+
const encoding = head[0] === 255 ? "utf-16le" : "utf-16be";
|
|
1407
|
+
return headBytes(new TextDecoder(encoding).decode(head.subarray(0, SNIFF_HEAD_BYTES)));
|
|
1408
|
+
}
|
|
1409
|
+
return head.byteLength > SNIFF_HEAD_BYTES ? head.subarray(0, SNIFF_HEAD_BYTES) : head;
|
|
1410
|
+
}
|
|
1411
|
+
function rankFormats(hints, importers) {
|
|
1412
|
+
const extension = typeof hints.filename === "string" ? extensionOf(hints.filename) : null;
|
|
1413
|
+
const mime = typeof hints.mimeType === "string" ? normalizeMimeType(hints.mimeType) : null;
|
|
1414
|
+
const head = hints.head === void 0 || hints.head === null ? null : headBytes(hints.head);
|
|
1415
|
+
const candidates = [];
|
|
1416
|
+
let rank = 0;
|
|
1417
|
+
for (const importer of importers) {
|
|
1418
|
+
const extensionMatch = extension !== null && importer.extensions.some((e) => e.toLowerCase() === extension);
|
|
1419
|
+
const mimeMatch = mime !== null && importer.mimeTypes.some((m) => m.toLowerCase() === mime);
|
|
1420
|
+
let content = 0;
|
|
1421
|
+
if (head !== null && head.byteLength > 0 && typeof importer.sniff === "function") {
|
|
1422
|
+
content = clamp(importer.sniff(head));
|
|
1423
|
+
}
|
|
1424
|
+
let confidence;
|
|
1425
|
+
if (content > 0) {
|
|
1426
|
+
confidence = 0.5 + 0.35 * content + (extensionMatch ? 0.1 : 0) + (mimeMatch ? 0.05 : 0);
|
|
1427
|
+
} else if (extensionMatch || mimeMatch) {
|
|
1428
|
+
confidence = (extensionMatch ? 0.3 : 0) + (mimeMatch ? 0.1 : 0);
|
|
1429
|
+
} else {
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
const dialect = importer.format === "json" && head !== null ? sniffJsonDialectHead(head) : null;
|
|
1433
|
+
const result = Object.freeze({
|
|
1434
|
+
format: importer.format,
|
|
1435
|
+
confidence: Math.min(1, confidence),
|
|
1436
|
+
content,
|
|
1437
|
+
extension: extensionMatch,
|
|
1438
|
+
mimeType: mimeMatch,
|
|
1439
|
+
dialect
|
|
1440
|
+
});
|
|
1441
|
+
candidates.push({ result, rank: rank++ });
|
|
1442
|
+
}
|
|
1443
|
+
candidates.sort((a, b) => b.result.confidence - a.result.confidence || a.rank - b.rank);
|
|
1444
|
+
return candidates.map((c) => c.result);
|
|
1445
|
+
}
|
|
1446
|
+
function sniffFormat(hints, importers) {
|
|
1447
|
+
const ranked = rankFormats(hints, importers);
|
|
1448
|
+
return ranked.length > 0 ? ranked[0] : null;
|
|
1449
|
+
}
|
|
1450
|
+
function sniffJsonDialectHead(head) {
|
|
1451
|
+
const text = typeof head === "string" ? head : new TextDecoder("utf-8", { fatal: false }).decode(head);
|
|
1452
|
+
const body = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
1453
|
+
const trimmed = body.trimStart();
|
|
1454
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
|
1455
|
+
return null;
|
|
1456
|
+
}
|
|
1457
|
+
let root;
|
|
1458
|
+
try {
|
|
1459
|
+
root = JSON.parse(trimmed);
|
|
1460
|
+
} catch {
|
|
1461
|
+
root = skeletonOf(trimmed);
|
|
1462
|
+
}
|
|
1463
|
+
return sniffJsonDialect(root);
|
|
1464
|
+
}
|
|
1465
|
+
function skeletonOf(text) {
|
|
1466
|
+
const keys = scanKeys(text);
|
|
1467
|
+
if (text.startsWith("[")) {
|
|
1468
|
+
const first = keys.get("nodes[0]");
|
|
1469
|
+
return first === void 0 ? null : [objectOf(first)];
|
|
1470
|
+
}
|
|
1471
|
+
const rootKeys = keys.get("");
|
|
1472
|
+
if (rootKeys === void 0) {
|
|
1473
|
+
return null;
|
|
1474
|
+
}
|
|
1475
|
+
const root = {};
|
|
1476
|
+
for (const key of rootKeys) {
|
|
1477
|
+
switch (key) {
|
|
1478
|
+
case "graph":
|
|
1479
|
+
case "options":
|
|
1480
|
+
root[key] = objectOf(keys.get(key));
|
|
1481
|
+
break;
|
|
1482
|
+
case "graphs": {
|
|
1483
|
+
const nodes = keys.get("graphs[0].nodes[]");
|
|
1484
|
+
const edges = keys.get("graphs[0].edges[]");
|
|
1485
|
+
const graph = {};
|
|
1486
|
+
if (nodes !== void 0) {
|
|
1487
|
+
graph.nodes = [objectOf(nodes)];
|
|
1488
|
+
}
|
|
1489
|
+
if (edges !== void 0) {
|
|
1490
|
+
graph.edges = [objectOf(edges)];
|
|
1491
|
+
}
|
|
1492
|
+
root[key] = nodes === void 0 && edges === void 0 ? [] : [graph];
|
|
1493
|
+
break;
|
|
1494
|
+
}
|
|
1495
|
+
case "nodes":
|
|
1496
|
+
case "edges":
|
|
1497
|
+
case "links": {
|
|
1498
|
+
const first = keys.get(`${key}[0]`);
|
|
1499
|
+
root[key] = first === void 0 ? [] : [objectOf(first)];
|
|
1500
|
+
break;
|
|
1501
|
+
}
|
|
1502
|
+
default:
|
|
1503
|
+
root[key] = true;
|
|
1504
|
+
break;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
return root;
|
|
1508
|
+
}
|
|
1509
|
+
function objectOf(names) {
|
|
1510
|
+
const out = {};
|
|
1511
|
+
if (names !== void 0) {
|
|
1512
|
+
for (const name of names) {
|
|
1513
|
+
out[name] = name === "attributes" || name === "data" ? {} : true;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return out;
|
|
1517
|
+
}
|
|
1518
|
+
function scanKeys(text) {
|
|
1519
|
+
const found = /* @__PURE__ */ new Map();
|
|
1520
|
+
const kinds = [];
|
|
1521
|
+
const labels = [];
|
|
1522
|
+
const counts = [];
|
|
1523
|
+
let pendingKey = null;
|
|
1524
|
+
let expectingKey = false;
|
|
1525
|
+
const pathOf = () => {
|
|
1526
|
+
const depth = kinds.length;
|
|
1527
|
+
if (depth === 1) {
|
|
1528
|
+
return kinds[0] === "object" ? "" : null;
|
|
1529
|
+
}
|
|
1530
|
+
if (depth === 2 && kinds[0] === "array" && kinds[1] === "object" && labels[1] === "0") {
|
|
1531
|
+
return "nodes[0]";
|
|
1532
|
+
}
|
|
1533
|
+
if (depth === 2 && kinds[0] === "object" && kinds[1] === "object") {
|
|
1534
|
+
return labels[1] === "graph" || labels[1] === "options" ? labels[1] : null;
|
|
1535
|
+
}
|
|
1536
|
+
if (depth === 5 && kinds.join() === "object,array,object,array,object" && labels[1] === "graphs" && labels[2] === "0" && (labels[3] === "nodes" || labels[3] === "edges")) {
|
|
1537
|
+
return labels[3] === "nodes" ? "graphs[0].nodes[]" : "graphs[0].edges[]";
|
|
1538
|
+
}
|
|
1539
|
+
if (depth === 3 && kinds[0] === "object" && kinds[1] === "array" && kinds[2] === "object") {
|
|
1540
|
+
const section = labels[1];
|
|
1541
|
+
if ((section === "nodes" || section === "edges" || section === "links") && labels[2] === "0") {
|
|
1542
|
+
return `${section}[0]`;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return null;
|
|
1546
|
+
};
|
|
1547
|
+
let i = 0;
|
|
1548
|
+
const n = text.length;
|
|
1549
|
+
while (i < n) {
|
|
1550
|
+
const ch = text[i];
|
|
1551
|
+
if (ch === '"') {
|
|
1552
|
+
const end = scanString(text, i + 1);
|
|
1553
|
+
if (end < 0) {
|
|
1554
|
+
break;
|
|
1555
|
+
}
|
|
1556
|
+
const literal = text.slice(i + 1, end);
|
|
1557
|
+
i = end + 1;
|
|
1558
|
+
if (expectingKey) {
|
|
1559
|
+
pendingKey = decodeKey(literal);
|
|
1560
|
+
expectingKey = false;
|
|
1561
|
+
}
|
|
1562
|
+
continue;
|
|
1563
|
+
}
|
|
1564
|
+
if (ch === "{" || ch === "[") {
|
|
1565
|
+
let label = "";
|
|
1566
|
+
if (kinds.length > 0) {
|
|
1567
|
+
label = kinds[kinds.length - 1] === "object" ? pendingKey ?? "" : String(counts[counts.length - 1]);
|
|
1568
|
+
}
|
|
1569
|
+
kinds.push(ch === "{" ? "object" : "array");
|
|
1570
|
+
labels.push(label);
|
|
1571
|
+
counts.push(0);
|
|
1572
|
+
expectingKey = ch === "{";
|
|
1573
|
+
pendingKey = null;
|
|
1574
|
+
} else if (ch === "}" || ch === "]") {
|
|
1575
|
+
kinds.pop();
|
|
1576
|
+
labels.pop();
|
|
1577
|
+
counts.pop();
|
|
1578
|
+
expectingKey = false;
|
|
1579
|
+
pendingKey = null;
|
|
1580
|
+
} else if (ch === ":") {
|
|
1581
|
+
if (pendingKey !== null) {
|
|
1582
|
+
const path = pathOf();
|
|
1583
|
+
if (path !== null) {
|
|
1584
|
+
let set = found.get(path);
|
|
1585
|
+
if (set === void 0) {
|
|
1586
|
+
set = /* @__PURE__ */ new Set();
|
|
1587
|
+
found.set(path, set);
|
|
1588
|
+
}
|
|
1589
|
+
set.add(pendingKey);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
} else if (ch === ",") {
|
|
1593
|
+
const top = kinds.length - 1;
|
|
1594
|
+
if (top >= 0) {
|
|
1595
|
+
counts[top]++;
|
|
1596
|
+
expectingKey = kinds[top] === "object";
|
|
1597
|
+
}
|
|
1598
|
+
pendingKey = null;
|
|
1599
|
+
}
|
|
1600
|
+
i++;
|
|
1601
|
+
}
|
|
1602
|
+
return found;
|
|
1603
|
+
}
|
|
1604
|
+
function scanString(text, from) {
|
|
1605
|
+
let i = from;
|
|
1606
|
+
while (i < text.length) {
|
|
1607
|
+
const ch = text[i];
|
|
1608
|
+
if (ch === "\\") {
|
|
1609
|
+
i += 2;
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
if (ch === '"') {
|
|
1613
|
+
return i;
|
|
1614
|
+
}
|
|
1615
|
+
i++;
|
|
1616
|
+
}
|
|
1617
|
+
return -1;
|
|
1618
|
+
}
|
|
1619
|
+
function decodeKey(literal) {
|
|
1620
|
+
if (!literal.includes("\\")) {
|
|
1621
|
+
return literal;
|
|
1622
|
+
}
|
|
1623
|
+
try {
|
|
1624
|
+
return JSON.parse(`"${literal}"`);
|
|
1625
|
+
} catch {
|
|
1626
|
+
return literal;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
function clamp(value) {
|
|
1630
|
+
if (!(value > 0)) {
|
|
1631
|
+
return 0;
|
|
1632
|
+
}
|
|
1633
|
+
return value > 1 ? 1 : value;
|
|
1634
|
+
}
|
|
1635
|
+
const NODE_KEYS = /* @__PURE__ */ new Set(["id", "lbl", "type", "propertyType", "meta"]);
|
|
1636
|
+
const META_KEYS = /* @__PURE__ */ new Set([
|
|
1637
|
+
"definition",
|
|
1638
|
+
"comments",
|
|
1639
|
+
"subsets",
|
|
1640
|
+
"xrefs",
|
|
1641
|
+
"synonyms",
|
|
1642
|
+
"basicPropertyValues",
|
|
1643
|
+
"deprecated"
|
|
1644
|
+
]);
|
|
1645
|
+
const FRAME_TYPES = Object.freeze({
|
|
1646
|
+
CLASS: "Term",
|
|
1647
|
+
INDIVIDUAL: "Instance",
|
|
1648
|
+
PROPERTY: "Typedef"
|
|
1649
|
+
});
|
|
1650
|
+
const BUILTIN_PREDICATES = Object.freeze({
|
|
1651
|
+
is_a: "is_a",
|
|
1652
|
+
subPropertyOf: "is_a",
|
|
1653
|
+
type: "instance_of",
|
|
1654
|
+
inverseOf: "inverse_of"
|
|
1655
|
+
});
|
|
1656
|
+
const PROPERTY_PREDICATES = /* @__PURE__ */ new Set(["subPropertyOf", "inverseOf"]);
|
|
1657
|
+
class ColumnWriter {
|
|
1658
|
+
/**
|
|
1659
|
+
* Create a writer.
|
|
1660
|
+
* @param ctx - the import context
|
|
1661
|
+
*/
|
|
1662
|
+
constructor(ctx) {
|
|
1663
|
+
this.handles = /* @__PURE__ */ new Map();
|
|
1664
|
+
this.ctx = ctx;
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Write a node cell of the vocabulary.
|
|
1668
|
+
* @param name - the column
|
|
1669
|
+
* @param row - the node index
|
|
1670
|
+
* @param value - the value
|
|
1671
|
+
*/
|
|
1672
|
+
node(name, row, value) {
|
|
1673
|
+
this.ctx.sink.setNodeValue(this.handle("node", name), row, value);
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Write an edge cell of the vocabulary.
|
|
1677
|
+
* @param name - the column
|
|
1678
|
+
* @param row - the edge index
|
|
1679
|
+
* @param value - the value
|
|
1680
|
+
*/
|
|
1681
|
+
edge(name, row, value) {
|
|
1682
|
+
this.ctx.sink.setEdgeValue(this.handle("edge", name), row, value);
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* The handle of a column, declared on first use.
|
|
1686
|
+
* @param domain - node or edge
|
|
1687
|
+
* @param name - the column
|
|
1688
|
+
* @returns the handle
|
|
1689
|
+
*/
|
|
1690
|
+
handle(domain, name) {
|
|
1691
|
+
const key = `${domain}:${name}`;
|
|
1692
|
+
const cached = this.handles.get(key);
|
|
1693
|
+
if (cached !== void 0) {
|
|
1694
|
+
return cached;
|
|
1695
|
+
}
|
|
1696
|
+
const { handle } = declareResolved(this.ctx.sink, domain, oboColumnDecl(domain, name), this.ctx.report);
|
|
1697
|
+
this.handles.set(key, handle);
|
|
1698
|
+
return handle;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
function vocabularyOf(nodes, oboIds) {
|
|
1702
|
+
const shorthands = /* @__PURE__ */ new Map();
|
|
1703
|
+
const propertyIds = /* @__PURE__ */ new Set();
|
|
1704
|
+
for (const node of nodes) {
|
|
1705
|
+
if (!isJsonObject(node) || typeof node.id !== "string" || node.type !== "PROPERTY") {
|
|
1706
|
+
continue;
|
|
1707
|
+
}
|
|
1708
|
+
propertyIds.add(node.id);
|
|
1709
|
+
const shorthand = basicValues(node.meta).find((pv) => OBOGRAPHS_PREDICATE_TAGS.get(pv.pred) === "shorthand");
|
|
1710
|
+
if (shorthand !== void 0) {
|
|
1711
|
+
shorthands.set(node.id, shorthand.val);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
const compact = (iri) => oboIds === "curie" ? compactOboIri(iri) : iri;
|
|
1715
|
+
return {
|
|
1716
|
+
id: (iri) => oboIds === "curie" ? shorthands.get(iri) ?? compactOboIri(iri) : iri,
|
|
1717
|
+
relation: (pred) => BUILTIN_PREDICATES[pred] ?? shorthands.get(pred) ?? compact(pred),
|
|
1718
|
+
isProperty: (iri) => propertyIds.has(iri),
|
|
1719
|
+
properties: {}
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
function basicValues(meta) {
|
|
1723
|
+
if (!isJsonObject(meta) || !Array.isArray(meta.basicPropertyValues)) {
|
|
1724
|
+
return [];
|
|
1725
|
+
}
|
|
1726
|
+
return meta.basicPropertyValues.filter(
|
|
1727
|
+
(pv) => isJsonObject(pv) && typeof pv.pred === "string" && typeof pv.val === "string"
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
function strings(value) {
|
|
1731
|
+
if (!Array.isArray(value)) {
|
|
1732
|
+
return [];
|
|
1733
|
+
}
|
|
1734
|
+
return value.flatMap((item) => {
|
|
1735
|
+
if (typeof item === "string") {
|
|
1736
|
+
return [item];
|
|
1737
|
+
}
|
|
1738
|
+
return isJsonObject(item) && typeof item.val === "string" ? [item.val] : [];
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
function importObographs(ctx, root) {
|
|
1742
|
+
const graph = chosenGraph(ctx, root, "OBO Graphs");
|
|
1743
|
+
const nodes = sectionOf(ctx, graph, "nodes");
|
|
1744
|
+
const edges = sectionOf(ctx, graph, "edges");
|
|
1745
|
+
const vocabulary = vocabularyOf(nodes, ctx.json.oboIds);
|
|
1746
|
+
const columns = new ColumnWriter(ctx);
|
|
1747
|
+
ctx.reportNodeIdFrom("obographs", "the node ids");
|
|
1748
|
+
ctx.setHeader(true);
|
|
1749
|
+
ctx.sink.reserve(nodes.length, edges.length);
|
|
1750
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1751
|
+
readNode(ctx, columns, vocabulary, nodes[i], `nodes[${i}]`);
|
|
1752
|
+
}
|
|
1753
|
+
const propertyEdges = readEdges(ctx, columns, vocabulary, edges);
|
|
1754
|
+
const graphMeta = {};
|
|
1755
|
+
for (const key of Object.keys(graph)) {
|
|
1756
|
+
if (key !== "nodes" && key !== "edges") {
|
|
1757
|
+
graphMeta[key] = graph[key];
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
const document = {};
|
|
1761
|
+
for (const key of Object.keys(root)) {
|
|
1762
|
+
if (key !== "graphs") {
|
|
1763
|
+
document[key] = root[key];
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
const label = typeof graph.lbl === "string" ? graph.lbl : null;
|
|
1767
|
+
const name = label ?? (typeof graph.id === "string" ? graph.id : null);
|
|
1768
|
+
ctx.sink.setMeta({
|
|
1769
|
+
sourceFormat: "json",
|
|
1770
|
+
name,
|
|
1771
|
+
extra: {
|
|
1772
|
+
json: { dialect: "obographs" },
|
|
1773
|
+
obographs: {
|
|
1774
|
+
ids: ctx.json.oboIds,
|
|
1775
|
+
graph: graphMeta,
|
|
1776
|
+
document,
|
|
1777
|
+
properties: vocabulary.properties,
|
|
1778
|
+
propertyEdges
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
function sectionOf(ctx, graph, key) {
|
|
1784
|
+
const value = graph[key];
|
|
1785
|
+
if (value === void 0 || value === null) {
|
|
1786
|
+
return [];
|
|
1787
|
+
}
|
|
1788
|
+
if (!Array.isArray(value)) {
|
|
1789
|
+
return ctx.report.fail(JSON_ISSUE.SHAPE, `an OBO Graphs graph's ${key} must be an array`, { element: key });
|
|
1790
|
+
}
|
|
1791
|
+
return value;
|
|
1792
|
+
}
|
|
1793
|
+
function readNode(ctx, columns, vocabulary, record, element) {
|
|
1794
|
+
if (!isJsonObject(record)) {
|
|
1795
|
+
ctx.badElement("node", element);
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
if (typeof record.id !== "string") {
|
|
1799
|
+
if (record.id === void 0) {
|
|
1800
|
+
ctx.coerceId(void 0, element);
|
|
1801
|
+
} else {
|
|
1802
|
+
badValue(ctx, `${element}.id must be a string; the node is skipped`);
|
|
1803
|
+
}
|
|
1804
|
+
ctx.countSkipped("node");
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
if (record.type === "PROPERTY" && ctx.json.typedefs === "metadata") {
|
|
1808
|
+
const shorthand = vocabulary.id(record.id) === record.id ? void 0 : vocabulary.id(record.id);
|
|
1809
|
+
const entry = {};
|
|
1810
|
+
for (const [key, value] of Object.entries({
|
|
1811
|
+
lbl: record.lbl,
|
|
1812
|
+
propertyType: record.propertyType,
|
|
1813
|
+
shorthand,
|
|
1814
|
+
meta: record.meta
|
|
1815
|
+
})) {
|
|
1816
|
+
if (value !== void 0) {
|
|
1817
|
+
entry[key] = value;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
vocabulary.properties[record.id] = entry;
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
const id = ctx.coerceId(vocabulary.id(record.id), element);
|
|
1824
|
+
const row = id === null ? -1 : ctx.pushNode(id, element);
|
|
1825
|
+
if (row < 0) {
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
try {
|
|
1829
|
+
writeNode(ctx, columns, vocabulary, record, row, element);
|
|
1830
|
+
} catch (err) {
|
|
1831
|
+
ctx.report.recordError(err, { element: record.id });
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
function writeNode(ctx, columns, vocabulary, record, row, element) {
|
|
1835
|
+
const unrecognized = {};
|
|
1836
|
+
const text = (key, column) => {
|
|
1837
|
+
const value = record[key];
|
|
1838
|
+
if (typeof value === "string") {
|
|
1839
|
+
columns.node(column, row, column === "type" ? FRAME_TYPES[value] ?? value : value);
|
|
1840
|
+
} else if (value !== void 0 && value !== null) {
|
|
1841
|
+
badValue(ctx, `${element}.${key} must be a string`);
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1844
|
+
text("type", "type");
|
|
1845
|
+
text("lbl", "name");
|
|
1846
|
+
text("propertyType", "propertyType");
|
|
1847
|
+
for (const key of Object.keys(record)) {
|
|
1848
|
+
if (!NODE_KEYS.has(key)) {
|
|
1849
|
+
unrecognized[key] = record[key];
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
const { meta } = record;
|
|
1853
|
+
if (isJsonObject(meta)) {
|
|
1854
|
+
writeMeta(columns, vocabulary, meta, row, unrecognized);
|
|
1855
|
+
} else if (meta !== void 0 && meta !== null) {
|
|
1856
|
+
badValue(ctx, `${element}.meta must be an object`);
|
|
1857
|
+
}
|
|
1858
|
+
if (Object.keys(unrecognized).length > 0) {
|
|
1859
|
+
columns.node("obo.unrecognized", row, unrecognized);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
function writeMeta(columns, vocabulary, meta, row, unrecognized) {
|
|
1863
|
+
const { definition } = meta;
|
|
1864
|
+
if (isJsonObject(definition) && typeof definition.val === "string") {
|
|
1865
|
+
columns.node("def", row, definition.val);
|
|
1866
|
+
columns.node("def.xrefs", row, strings(definition.xrefs));
|
|
1867
|
+
}
|
|
1868
|
+
const comments = strings(meta.comments);
|
|
1869
|
+
if (comments.length > 0) {
|
|
1870
|
+
columns.node("comment", row, comments.join("\n"));
|
|
1871
|
+
}
|
|
1872
|
+
const subsets = strings(meta.subsets).map((s) => vocabulary.id(s));
|
|
1873
|
+
if (subsets.length > 0) {
|
|
1874
|
+
columns.node("subset", row, subsets);
|
|
1875
|
+
}
|
|
1876
|
+
const xrefs = strings(meta.xrefs);
|
|
1877
|
+
if (xrefs.length > 0) {
|
|
1878
|
+
columns.node("xref", row, xrefs);
|
|
1879
|
+
}
|
|
1880
|
+
if (Array.isArray(meta.synonyms) && meta.synonyms.length > 0) {
|
|
1881
|
+
columns.node(
|
|
1882
|
+
"synonym",
|
|
1883
|
+
row,
|
|
1884
|
+
meta.synonyms.filter(isJsonObject).map((s) => ({
|
|
1885
|
+
text: typeof s.val === "string" ? s.val : null,
|
|
1886
|
+
scope: typeof s.pred === "string" ? synonymScopeOf(s.pred) : null,
|
|
1887
|
+
type: typeof s.synonymType === "string" ? vocabulary.id(s.synonymType) : null,
|
|
1888
|
+
xrefs: strings(s.xrefs)
|
|
1889
|
+
}))
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
if (typeof meta.deprecated === "boolean") {
|
|
1893
|
+
columns.node("is_obsolete", row, meta.deprecated);
|
|
1894
|
+
}
|
|
1895
|
+
writePropertyValues(columns, vocabulary, basicValues(meta), row);
|
|
1896
|
+
for (const key of Object.keys(meta)) {
|
|
1897
|
+
if (!META_KEYS.has(key)) {
|
|
1898
|
+
unrecognized[`meta.${key}`] = meta[key];
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
function writePropertyValues(columns, vocabulary, values, row) {
|
|
1903
|
+
const lists = /* @__PURE__ */ new Map();
|
|
1904
|
+
const others = [];
|
|
1905
|
+
for (const { pred, val } of values) {
|
|
1906
|
+
const tag = OBOGRAPHS_PREDICATE_TAGS.get(pred);
|
|
1907
|
+
if (tag === "shorthand") {
|
|
1908
|
+
continue;
|
|
1909
|
+
}
|
|
1910
|
+
if (tag === void 0) {
|
|
1911
|
+
others.push({ relation: vocabulary.id(pred), value: val, datatype: null });
|
|
1912
|
+
} else if (OBO_NODE_COLUMNS[tag].dtype === "list") {
|
|
1913
|
+
const list = lists.get(tag) ?? [];
|
|
1914
|
+
list.push(tag === "alt_id" ? val : vocabulary.id(val));
|
|
1915
|
+
lists.set(tag, list);
|
|
1916
|
+
} else {
|
|
1917
|
+
columns.node(tag, row, val);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
for (const [tag, list] of lists) {
|
|
1921
|
+
columns.node(tag, row, list);
|
|
1922
|
+
}
|
|
1923
|
+
if (others.length > 0) {
|
|
1924
|
+
columns.node("property_value", row, others);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
function badValue(ctx, message) {
|
|
1928
|
+
ctx.report.error("validation-error", JSON_ISSUE.BAD_VALUE, message);
|
|
1929
|
+
}
|
|
1930
|
+
function readEdges(ctx, columns, vocabulary, edges) {
|
|
1931
|
+
const { report, sink } = ctx;
|
|
1932
|
+
const propertyEdges = [];
|
|
1933
|
+
const dangling = [];
|
|
1934
|
+
let dropped = 0;
|
|
1935
|
+
const endpoint = (raw, element) => {
|
|
1936
|
+
const id = ctx.coerceId(vocabulary.id(raw), element);
|
|
1937
|
+
if (id === null || sink.indexOf(id) !== INVALID_INDEX) {
|
|
1938
|
+
return id;
|
|
1939
|
+
}
|
|
1940
|
+
dangling.push(raw);
|
|
1941
|
+
if (!ctx.options.addMissingNodes) {
|
|
1942
|
+
return null;
|
|
1943
|
+
}
|
|
1944
|
+
const row = ctx.pushNode(id, element);
|
|
1945
|
+
if (row >= 0) {
|
|
1946
|
+
columns.node(PLACEHOLDER_COLUMN, row, true);
|
|
1947
|
+
}
|
|
1948
|
+
return id;
|
|
1949
|
+
};
|
|
1950
|
+
for (let i = 0; i < edges.length; i++) {
|
|
1951
|
+
const element = `edges[${i}]`;
|
|
1952
|
+
const record = edges[i];
|
|
1953
|
+
if (!isJsonObject(record)) {
|
|
1954
|
+
ctx.badElement("edge", element);
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
const subKey = hasKey(record, "sub") ? "sub" : "subj";
|
|
1958
|
+
if (subKey === "subj" && hasKey(record, "subj")) {
|
|
1959
|
+
report.warnOnce(
|
|
1960
|
+
"coercion",
|
|
1961
|
+
JSON_ISSUE.OBOGRAPHS_SUBJ,
|
|
1962
|
+
`${element} uses the outdated key subj; read as sub`,
|
|
1963
|
+
{
|
|
1964
|
+
element
|
|
1965
|
+
}
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
const sub = record[subKey];
|
|
1969
|
+
const { obj, pred } = record;
|
|
1970
|
+
if (typeof sub !== "string" || typeof obj !== "string") {
|
|
1971
|
+
ctx.missingEndpoint(element, typeof sub === "string" ? "obj" : "sub");
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1974
|
+
const between = typeof pred === "string" && PROPERTY_PREDICATES.has(pred) || vocabulary.isProperty(sub) || vocabulary.isProperty(obj);
|
|
1975
|
+
if (between && ctx.json.typedefs === "metadata") {
|
|
1976
|
+
propertyEdges.push(record);
|
|
1977
|
+
continue;
|
|
1978
|
+
}
|
|
1979
|
+
try {
|
|
1980
|
+
const u = endpoint(sub, `${element}.sub`);
|
|
1981
|
+
const v = endpoint(obj, `${element}.obj`);
|
|
1982
|
+
if (u === null || v === null) {
|
|
1983
|
+
dropped++;
|
|
1984
|
+
ctx.countSkipped("edge");
|
|
1985
|
+
continue;
|
|
1986
|
+
}
|
|
1987
|
+
const edge = ctx.pushEdge(u, v, "directed", void 0, element);
|
|
1988
|
+
if (typeof pred === "string") {
|
|
1989
|
+
columns.edge("relation", edge, vocabulary.relation(pred));
|
|
1990
|
+
} else {
|
|
1991
|
+
badValue(ctx, `${element} has no pred; its relation is unset`);
|
|
1992
|
+
}
|
|
1993
|
+
if (isJsonObject(record.meta)) {
|
|
1994
|
+
columns.edge("meta", edge, record.meta);
|
|
1995
|
+
}
|
|
1996
|
+
} catch (err) {
|
|
1997
|
+
ctx.skip(err, "edge", element);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
if (dangling.length > 0) {
|
|
2001
|
+
const shown = [...new Set(dangling)].slice(0, 5).join(", ");
|
|
2002
|
+
const action = ctx.options.addMissingNodes ? "each became a placeholder node (graphty.placeholder)" : `${dropped} edge(s) to them were dropped (addMissingNodes false)`;
|
|
2003
|
+
report.warning(
|
|
2004
|
+
"validation-error",
|
|
2005
|
+
JSON_ISSUE.DANGLING_REFERENCE,
|
|
2006
|
+
`${new Set(dangling).size} edge endpoint(s) missing from nodes: ${shown}; ${action}`,
|
|
2007
|
+
{ element: dangling[0] }
|
|
2008
|
+
);
|
|
2009
|
+
}
|
|
2010
|
+
return propertyEdges;
|
|
2011
|
+
}
|
|
1359
2012
|
const JSON_ISSUE = Object.freeze({
|
|
1360
2013
|
/** The text is empty or whitespace (fatal). */
|
|
1361
2014
|
EMPTY_INPUT: EMPTY_INPUT_CODE,
|
|
@@ -1391,8 +2044,18 @@ const JSON_ISSUE = Object.freeze({
|
|
|
1391
2044
|
ID_MERGED: ID_MERGED_CODE,
|
|
1392
2045
|
/** Edge ids of mixed JSON types were stored as text. */
|
|
1393
2046
|
EDGE_ID_STRINGIFIED: "W_EDGE_ID_STRINGIFIED",
|
|
1394
|
-
/** A JGF `graphs` array holds more than one graph; only
|
|
2047
|
+
/** A JGF or OBO Graphs `graphs` array holds more than one graph; only the chosen one is read. */
|
|
1395
2048
|
MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
|
|
2049
|
+
/** `graphIndex` is beyond the `graphs` array, or `graphName` names none of its graphs (fatal). */
|
|
2050
|
+
GRAPH_NOT_FOUND: GRAPH_NOT_FOUND_CODE,
|
|
2051
|
+
/** `graphName` names more than one graph of the `graphs` array (fatal). */
|
|
2052
|
+
AMBIGUOUS_GRAPH_NAME: AMBIGUOUS_GRAPH_NAME_CODE,
|
|
2053
|
+
/** obographs: an edge uses the outdated `subj` key of the OBO Graphs README; it is read as `sub`. */
|
|
2054
|
+
OBOGRAPHS_SUBJ: "W_JSON_OBOGRAPHS_SUBJ",
|
|
2055
|
+
/** obographs: an edge endpoint missing from `nodes` (a placeholder node is made, or the edge dropped under addMissingNodes false). */
|
|
2056
|
+
DANGLING_REFERENCE: DANGLING_REFERENCE_CODE,
|
|
2057
|
+
/** The document is longer than one JavaScript string can hold (fatal; category unsupported). */
|
|
2058
|
+
TOO_LARGE: TOO_LARGE_CODE,
|
|
1396
2059
|
/** JGF hyperedges under the "error" policy. */
|
|
1397
2060
|
HYPEREDGE: HYPEREDGE_CODE,
|
|
1398
2061
|
/** JGF hyperedges skipped under the default "skip" policy. */
|
|
@@ -1475,6 +2138,14 @@ function resolveJsonOptions(options) {
|
|
|
1475
2138
|
if (!Number.isInteger(graphIndex) || graphIndex < 0) {
|
|
1476
2139
|
throw unsupportedOption("graphIndex", graphIndex, ["a non-negative integer"]);
|
|
1477
2140
|
}
|
|
2141
|
+
const oboIds = o.oboIds ?? "curie";
|
|
2142
|
+
if (oboIds !== "curie" && oboIds !== "iri") {
|
|
2143
|
+
throw unsupportedOption("oboIds", oboIds, ["curie", "iri"]);
|
|
2144
|
+
}
|
|
2145
|
+
const typedefs = o.typedefs ?? "metadata";
|
|
2146
|
+
if (typedefs !== "metadata" && typedefs !== "nodes") {
|
|
2147
|
+
throw unsupportedOption("typedefs", typedefs, ["metadata", "nodes"]);
|
|
2148
|
+
}
|
|
1478
2149
|
const nodesPath = pathOption("nodesPath", o.nodesPath);
|
|
1479
2150
|
const edgesPath = pathOption("edgesPath", o.edgesPath);
|
|
1480
2151
|
if ((nodesPath !== null || edgesPath !== null) && dialect !== "auto" && !PATH_DIALECTS.has(dialect)) {
|
|
@@ -1488,6 +2159,9 @@ function resolveJsonOptions(options) {
|
|
|
1488
2159
|
targetKey: keyOption("targetKey", o.targetKey),
|
|
1489
2160
|
indexLinks,
|
|
1490
2161
|
graphIndex,
|
|
2162
|
+
choice: { graphIndex: o.graphIndex, graphName: o.graphName },
|
|
2163
|
+
oboIds,
|
|
2164
|
+
typedefs,
|
|
1491
2165
|
nodesPath,
|
|
1492
2166
|
edgesPath
|
|
1493
2167
|
};
|
|
@@ -2059,7 +2733,7 @@ class ImportContext {
|
|
|
2059
2733
|
*/
|
|
2060
2734
|
declareEdgeIds(edges, read, name, unique) {
|
|
2061
2735
|
let numbers = 0;
|
|
2062
|
-
let
|
|
2736
|
+
let strings2 = 0;
|
|
2063
2737
|
for (const edge of edges) {
|
|
2064
2738
|
if (!isJsonObject(edge)) {
|
|
2065
2739
|
continue;
|
|
@@ -2068,16 +2742,16 @@ class ImportContext {
|
|
|
2068
2742
|
if (typeof raw === "number") {
|
|
2069
2743
|
numbers++;
|
|
2070
2744
|
} else if (typeof raw === "string") {
|
|
2071
|
-
|
|
2745
|
+
strings2++;
|
|
2072
2746
|
}
|
|
2073
2747
|
}
|
|
2074
|
-
if (numbers +
|
|
2748
|
+
if (numbers + strings2 === 0) {
|
|
2075
2749
|
return null;
|
|
2076
2750
|
}
|
|
2077
|
-
const dtype =
|
|
2751
|
+
const dtype = strings2 === 0 ? "f64" : "string";
|
|
2078
2752
|
const columnName = uniqueColumnName(name, "id", (candidate) => this.edges.taken(candidate));
|
|
2079
2753
|
const handle = this.edges.declare({ name: columnName, dtype, role: "id", nullable: true, unique });
|
|
2080
|
-
const stringify =
|
|
2754
|
+
const stringify = strings2 > 0 && numbers > 0;
|
|
2081
2755
|
const seen = unique ? /* @__PURE__ */ new Set() : null;
|
|
2082
2756
|
if (stringify) {
|
|
2083
2757
|
this.report.warning(
|
|
@@ -2180,84 +2854,7 @@ function parseDocument(text, report) {
|
|
|
2180
2854
|
}
|
|
2181
2855
|
return root;
|
|
2182
2856
|
}
|
|
2183
|
-
const MAYBE_UNSAFE_INTEGER = new RegExp("(?<![0-9.])[0-9]{16}");
|
|
2184
2857
|
const BIG_INTEGERS_SHOWN = 10;
|
|
2185
|
-
const NONSTANDARD_SENTINEL = `${String.fromCharCode(0)}graph-io:`;
|
|
2186
|
-
const NONSTANDARD_TOKENS = [
|
|
2187
|
-
["-Infinity", -Infinity],
|
|
2188
|
-
["Infinity", Infinity],
|
|
2189
|
-
["NaN", NaN]
|
|
2190
|
-
];
|
|
2191
|
-
const INTEGER_LITERAL = /^-?(0|[1-9][0-9]*)$/;
|
|
2192
|
-
function rewriteNumbers(text) {
|
|
2193
|
-
const parts = [];
|
|
2194
|
-
const tokens = /* @__PURE__ */ new Set();
|
|
2195
|
-
const bigIntegers = [];
|
|
2196
|
-
const arrays = [];
|
|
2197
|
-
let expectValue = true;
|
|
2198
|
-
let copied = 0;
|
|
2199
|
-
let i = 0;
|
|
2200
|
-
const n = text.length;
|
|
2201
|
-
while (i < n) {
|
|
2202
|
-
const ch = text[i];
|
|
2203
|
-
if (ch === '"') {
|
|
2204
|
-
i++;
|
|
2205
|
-
while (i < n && text[i] !== '"') {
|
|
2206
|
-
i += text[i] === "\\" ? 2 : 1;
|
|
2207
|
-
}
|
|
2208
|
-
i++;
|
|
2209
|
-
expectValue = false;
|
|
2210
|
-
continue;
|
|
2211
|
-
}
|
|
2212
|
-
if (ch === "{" || ch === "[") {
|
|
2213
|
-
arrays.push(ch === "[");
|
|
2214
|
-
expectValue = ch === "[";
|
|
2215
|
-
} else if (ch === "}" || ch === "]") {
|
|
2216
|
-
arrays.pop();
|
|
2217
|
-
expectValue = false;
|
|
2218
|
-
} else if (ch === ":") {
|
|
2219
|
-
expectValue = true;
|
|
2220
|
-
} else if (ch === ",") {
|
|
2221
|
-
expectValue = arrays.length > 0 && arrays[arrays.length - 1];
|
|
2222
|
-
} else if (expectValue && ch !== " " && ch !== " " && ch !== "\n" && ch !== "\r") {
|
|
2223
|
-
expectValue = false;
|
|
2224
|
-
const token = NONSTANDARD_TOKENS.find(([word]) => text.startsWith(word, i));
|
|
2225
|
-
let end = i;
|
|
2226
|
-
let replacement = null;
|
|
2227
|
-
if (token !== void 0) {
|
|
2228
|
-
end = i + token[0].length;
|
|
2229
|
-
tokens.add(token[0]);
|
|
2230
|
-
replacement = JSON.stringify(`${NONSTANDARD_SENTINEL}${token[0]}`);
|
|
2231
|
-
} else if (ch === "-" || ch >= "0" && ch <= "9") {
|
|
2232
|
-
end = i + 1;
|
|
2233
|
-
while (end < n && "0123456789+-.eE".includes(text[end])) {
|
|
2234
|
-
end++;
|
|
2235
|
-
}
|
|
2236
|
-
const literal = text.slice(i, end);
|
|
2237
|
-
if (INTEGER_LITERAL.test(literal) && !Number.isSafeInteger(Number(literal))) {
|
|
2238
|
-
bigIntegers.push(literal);
|
|
2239
|
-
replacement = `"${literal}"`;
|
|
2240
|
-
}
|
|
2241
|
-
}
|
|
2242
|
-
if (replacement !== null) {
|
|
2243
|
-
parts.push(text.slice(copied, i), replacement);
|
|
2244
|
-
copied = end;
|
|
2245
|
-
}
|
|
2246
|
-
i = Math.max(end, i + 1);
|
|
2247
|
-
continue;
|
|
2248
|
-
}
|
|
2249
|
-
i++;
|
|
2250
|
-
}
|
|
2251
|
-
parts.push(text.slice(copied));
|
|
2252
|
-
return { text: parts.join(""), tokens, bigIntegers };
|
|
2253
|
-
}
|
|
2254
|
-
function reviveNonstandard(_key, value) {
|
|
2255
|
-
if (typeof value === "string" && value.startsWith(NONSTANDARD_SENTINEL)) {
|
|
2256
|
-
const found = NONSTANDARD_TOKENS.find(([word]) => word === value.slice(NONSTANDARD_SENTINEL.length));
|
|
2257
|
-
return found === void 0 ? value : found[1];
|
|
2258
|
-
}
|
|
2259
|
-
return value;
|
|
2260
|
-
}
|
|
2261
2858
|
function detectDialect(root, forced, report) {
|
|
2262
2859
|
if (forced !== "auto") {
|
|
2263
2860
|
return forced;
|
|
@@ -3029,31 +3626,84 @@ function importJgf(ctx, root) {
|
|
|
3029
3626
|
ctx.setMeta(shape, { name: label, ...ctx.weightOriginPatch() });
|
|
3030
3627
|
}
|
|
3031
3628
|
function jgfGraphOf(ctx, root) {
|
|
3629
|
+
return isJsonObject(root.graph) ? root.graph : chosenGraph(ctx, root, "JGF");
|
|
3630
|
+
}
|
|
3631
|
+
function chosenGraph(ctx, root, what) {
|
|
3032
3632
|
const { report } = ctx;
|
|
3033
|
-
if (isJsonObject(root.graph)) {
|
|
3034
|
-
return root.graph;
|
|
3035
|
-
}
|
|
3036
3633
|
const graphs = arraySection(root.graphs, "graphs", report) ?? [];
|
|
3037
3634
|
if (graphs.length === 0) {
|
|
3038
|
-
report.fail(JSON_ISSUE.SHAPE,
|
|
3635
|
+
report.fail(JSON_ISSUE.SHAPE, `a ${what} document needs a graph object or a non-empty graphs array`);
|
|
3039
3636
|
}
|
|
3637
|
+
const index = ctx.json.all === true ? ctx.json.graphIndex : chooseGraph(graphs.map(graphNameOf), ctx.json.choice, report);
|
|
3040
3638
|
if (graphs.length > 1 && ctx.json.all !== true) {
|
|
3041
3639
|
report.warning(
|
|
3042
3640
|
"unsupported",
|
|
3043
3641
|
JSON_ISSUE.MULTIPLE_GRAPHS,
|
|
3044
|
-
`the document holds ${graphs.length} graphs; only graphs[${
|
|
3642
|
+
`the document holds ${graphs.length} graphs; only graphs[${index}] is read (${graphs.length - 1} skipped), importAll() reads every one`,
|
|
3045
3643
|
{ element: "graphs" }
|
|
3046
3644
|
);
|
|
3047
3645
|
}
|
|
3048
|
-
|
|
3049
|
-
report.fail(JSON_ISSUE.SHAPE, `graphIndex ${ctx.json.graphIndex} is beyond the ${graphs.length} graph(s)`);
|
|
3050
|
-
}
|
|
3051
|
-
const graph = graphs[ctx.json.graphIndex];
|
|
3646
|
+
const graph = graphs[index];
|
|
3052
3647
|
if (!isJsonObject(graph)) {
|
|
3053
|
-
return report.fail(JSON_ISSUE.SHAPE, `graphs[${
|
|
3648
|
+
return report.fail(JSON_ISSUE.SHAPE, `graphs[${index}] is not an object`);
|
|
3054
3649
|
}
|
|
3055
3650
|
return graph;
|
|
3056
3651
|
}
|
|
3652
|
+
function graphNameOf(graph) {
|
|
3653
|
+
if (!isJsonObject(graph)) {
|
|
3654
|
+
return null;
|
|
3655
|
+
}
|
|
3656
|
+
for (const key of ["id", "label", "lbl"]) {
|
|
3657
|
+
if (typeof graph[key] === "string") {
|
|
3658
|
+
return graph[key];
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
return null;
|
|
3662
|
+
}
|
|
3663
|
+
function countOf(section) {
|
|
3664
|
+
if (section === void 0 || section === null) {
|
|
3665
|
+
return 0;
|
|
3666
|
+
}
|
|
3667
|
+
if (Array.isArray(section)) {
|
|
3668
|
+
return section.length;
|
|
3669
|
+
}
|
|
3670
|
+
return isJsonObject(section) ? Object.keys(section).length : null;
|
|
3671
|
+
}
|
|
3672
|
+
function listingsOf(root, dialect) {
|
|
3673
|
+
if ((dialect === "jgf" || dialect === "obographs") && isJsonObject(root)) {
|
|
3674
|
+
if (Array.isArray(root.graphs) && !isJsonObject(root.graph)) {
|
|
3675
|
+
return root.graphs.map((graph, index) => ({
|
|
3676
|
+
index,
|
|
3677
|
+
name: graphNameOf(graph),
|
|
3678
|
+
nodes: isJsonObject(graph) ? countOf(graph.nodes) : null,
|
|
3679
|
+
edges: isJsonObject(graph) ? countOf(graph.edges) : null
|
|
3680
|
+
}));
|
|
3681
|
+
}
|
|
3682
|
+
if (isJsonObject(root.graph)) {
|
|
3683
|
+
const { graph } = root;
|
|
3684
|
+
return [{ index: 0, name: graphNameOf(graph), nodes: countOf(graph.nodes), edges: countOf(graph.edges) }];
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
return [{ index: 0, name: null, nodes: null, edges: null }];
|
|
3688
|
+
}
|
|
3689
|
+
const MAX_TEXT_LENGTH = 2 ** 29 - 24;
|
|
3690
|
+
async function readJsonText(input, report, options) {
|
|
3691
|
+
if (typeof input === "string") {
|
|
3692
|
+
return readText(input, report, options);
|
|
3693
|
+
}
|
|
3694
|
+
const parts = [];
|
|
3695
|
+
let length = 0;
|
|
3696
|
+
for await (const chunk of textChunks(input, report, options)) {
|
|
3697
|
+
length += chunk.length;
|
|
3698
|
+
if (length > MAX_TEXT_LENGTH) {
|
|
3699
|
+
const message = `the document is longer than ${MAX_TEXT_LENGTH} characters, the most one JavaScript string holds`;
|
|
3700
|
+
report.error("unsupported", JSON_ISSUE.TOO_LARGE, message);
|
|
3701
|
+
throw report.abort(message, { code: JSON_ISSUE.TOO_LARGE });
|
|
3702
|
+
}
|
|
3703
|
+
parts.push(chunk);
|
|
3704
|
+
}
|
|
3705
|
+
return parts.length === 1 ? parts[0] : parts.join("");
|
|
3706
|
+
}
|
|
3057
3707
|
function pushJgfNode(ctx, id, record, labelColumn, element) {
|
|
3058
3708
|
const index = ctx.pushNode(id, element);
|
|
3059
3709
|
if (index < 0) {
|
|
@@ -3395,7 +4045,8 @@ const jsonImporter = Object.freeze({
|
|
|
3395
4045
|
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
|
3396
4046
|
return 0;
|
|
3397
4047
|
}
|
|
3398
|
-
|
|
4048
|
+
const score = SNIFF_KEYS.some((key) => trimmed.includes(key)) ? 0.9 : 0.5;
|
|
4049
|
+
return trimmed.startsWith("[") && sniffJsonDialectHead(trimmed) !== "cytoscape" ? Math.min(score, 0.3) : score;
|
|
3399
4050
|
},
|
|
3400
4051
|
/**
|
|
3401
4052
|
* Read a JSON graph document into the sink.
|
|
@@ -3408,11 +4059,27 @@ const jsonImporter = Object.freeze({
|
|
|
3408
4059
|
const resolved = resolveImportOptions(options, FORMAT_DEFAULTS);
|
|
3409
4060
|
const json = resolveJsonOptions(options);
|
|
3410
4061
|
const report = new ImportReportBuilder("json", resolved.errorLimit);
|
|
3411
|
-
const text = await
|
|
4062
|
+
const text = await readJsonText(input, report, resolved);
|
|
3412
4063
|
const { root, dialect } = documentOf(parseDocument(text, report), json, report);
|
|
3413
4064
|
readGraph(root, dialect, sink, report, resolved, json, options);
|
|
3414
4065
|
return report.finish();
|
|
3415
4066
|
},
|
|
4067
|
+
/**
|
|
4068
|
+
* List the graphs of a JSON document without importing them: each entry of a JGF or OBO
|
|
4069
|
+
* Graphs `graphs` array with its name (`id`, else its label) and node and edge counts; any
|
|
4070
|
+
* other document holds one graph.
|
|
4071
|
+
* @param input - the text, bytes or stream
|
|
4072
|
+
* @param options - format-specific and common options
|
|
4073
|
+
* @returns one listing per graph
|
|
4074
|
+
*/
|
|
4075
|
+
async listGraphs(input, options) {
|
|
4076
|
+
const resolved = resolveImportOptions(options, FORMAT_DEFAULTS);
|
|
4077
|
+
const json = resolveJsonOptions(options);
|
|
4078
|
+
const report = new ImportReportBuilder("json", resolved.errorLimit);
|
|
4079
|
+
const text = await readJsonText(input, report, resolved);
|
|
4080
|
+
const { root, dialect } = documentOf(parseDocument(text, report), json, report);
|
|
4081
|
+
return listingsOf(root, dialect);
|
|
4082
|
+
},
|
|
3416
4083
|
/**
|
|
3417
4084
|
* Read every graph of a JSON document: each entry of a JGF `graphs` array into its own sink;
|
|
3418
4085
|
* any other document holds one graph.
|
|
@@ -3425,9 +4092,9 @@ const jsonImporter = Object.freeze({
|
|
|
3425
4092
|
const resolved = resolveImportOptions(options, FORMAT_DEFAULTS);
|
|
3426
4093
|
const json = resolveJsonOptions(options);
|
|
3427
4094
|
const first = new ImportReportBuilder("json", resolved.errorLimit);
|
|
3428
|
-
const text = await
|
|
4095
|
+
const text = await readJsonText(input, first, resolved);
|
|
3429
4096
|
const { root, dialect } = documentOf(parseDocument(text, first), json, first);
|
|
3430
|
-
const graphs =
|
|
4097
|
+
const graphs = listingsOf(root, dialect).length;
|
|
3431
4098
|
const reports = [];
|
|
3432
4099
|
for (let i = 0; i < Math.max(graphs, 1); i++) {
|
|
3433
4100
|
const report = i === 0 ? first : new ImportReportBuilder("json", resolved.errorLimit);
|
|
@@ -3439,7 +4106,7 @@ const jsonImporter = Object.freeze({
|
|
|
3439
4106
|
});
|
|
3440
4107
|
function readGraph(root, dialect, sink, report, resolved, json, options) {
|
|
3441
4108
|
const ctx = new ImportContext(sink, report, resolved, json, options?.defaultDirected !== void 0);
|
|
3442
|
-
reportSinkOptions(sink, options, report);
|
|
4109
|
+
reportSinkOptions(sink, options, report, dialect === "obographs");
|
|
3443
4110
|
reportUnusedOptions(options, report, USED_OPTIONS);
|
|
3444
4111
|
if (dialect === "cytoscape") {
|
|
3445
4112
|
importCytoscape(ctx, root);
|
|
@@ -3467,6 +4134,9 @@ function readGraph(root, dialect, sink, report, resolved, json, options) {
|
|
|
3467
4134
|
case "tree":
|
|
3468
4135
|
importTree(ctx, doc);
|
|
3469
4136
|
break;
|
|
4137
|
+
case "obographs":
|
|
4138
|
+
importObographs(ctx, doc);
|
|
4139
|
+
break;
|
|
3470
4140
|
default: {
|
|
3471
4141
|
const name = dialect;
|
|
3472
4142
|
throw new GraphFormatError("E_UNSUPPORTED", `unknown dialect ${name}`, {
|
|
@@ -3478,13 +4148,20 @@ function readGraph(root, dialect, sink, report, resolved, json, options) {
|
|
|
3478
4148
|
throwIfAborted(resolved.signal);
|
|
3479
4149
|
}
|
|
3480
4150
|
export {
|
|
4151
|
+
GRAPH_FORMATS as G,
|
|
3481
4152
|
JSON_DIALECTS as J,
|
|
4153
|
+
SNIFF_HEAD_BYTES as S,
|
|
3482
4154
|
JSON_ISSUE as a,
|
|
3483
4155
|
JSON_LOSS as b,
|
|
3484
4156
|
jsonExporter as c,
|
|
3485
4157
|
dialectCapabilities as d,
|
|
3486
4158
|
jsonImporter as e,
|
|
4159
|
+
extensionOf as f,
|
|
4160
|
+
sniffJsonDialectHead as g,
|
|
4161
|
+
headBytes as h,
|
|
3487
4162
|
jsonCapabilities as j,
|
|
3488
|
-
|
|
4163
|
+
normalizeMimeType as n,
|
|
4164
|
+
rankFormats as r,
|
|
4165
|
+
sniffFormat as s
|
|
3489
4166
|
};
|
|
3490
|
-
//# sourceMappingURL=importer-
|
|
4167
|
+
//# sourceMappingURL=importer-Bm1_5vPS.js.map
|