@graphty/graph-io 0.3.25 → 0.3.27
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 +49 -414
- package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
- package/dist/chunks/choose-DrXtu_96.js +56 -0
- package/dist/chunks/choose-DrXtu_96.js.map +1 -0
- package/dist/chunks/constants-ikG85dT8.js +231 -0
- package/dist/chunks/constants-ikG85dT8.js.map +1 -0
- package/dist/chunks/{escape-B-tkk_Cl.js → escape-D1HPTUrP.js} +390 -99
- package/dist/chunks/escape-D1HPTUrP.js.map +1 -0
- package/dist/chunks/export-CHd4tQE2.js +4333 -0
- package/dist/chunks/export-CHd4tQE2.js.map +1 -0
- package/dist/chunks/{importer-eUREhBGj.js → exporter-D23CKNqF.js} +4969 -3201
- package/dist/chunks/exporter-D23CKNqF.js.map +1 -0
- package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-DfWTgrti.js} +23 -21
- package/dist/chunks/exporter-DfWTgrti.js.map +1 -0
- package/dist/chunks/exporter-DhtW6FxK.js +3465 -0
- package/dist/chunks/exporter-DhtW6FxK.js.map +1 -0
- package/dist/chunks/{exporter-BGrsWamJ.js → exporter-IHv4nkCm.js} +38 -229
- package/dist/chunks/exporter-IHv4nkCm.js.map +1 -0
- package/dist/chunks/{importer-BWY2FFc5.js → importer-B1wmPQjr.js} +255 -77
- package/dist/chunks/importer-B1wmPQjr.js.map +1 -0
- package/dist/chunks/{importer-D_e7e7LX.js → importer-B2W_58pz.js} +399 -146
- package/dist/chunks/importer-B2W_58pz.js.map +1 -0
- package/dist/chunks/importer-BSALvkui.js +2811 -0
- package/dist/chunks/importer-BSALvkui.js.map +1 -0
- package/dist/chunks/{importer-vi3bSdtw.js → importer-BVRE--Un.js} +510 -77
- package/dist/chunks/importer-BVRE--Un.js.map +1 -0
- package/dist/chunks/{importer-DET1tg6s.js → importer-CIAzt-wo.js} +1689 -312
- package/dist/chunks/importer-CIAzt-wo.js.map +1 -0
- package/dist/chunks/{importer-DIrbbnAf.js → importer-DpEW5zeG.js} +585 -226
- package/dist/chunks/importer-DpEW5zeG.js.map +1 -0
- package/dist/chunks/{importer-zGLo8Dg_.js → importer-z_FL4VMb.js} +488 -161
- package/dist/chunks/importer-z_FL4VMb.js.map +1 -0
- package/dist/chunks/json-elements-BAmNBZok.js +1225 -0
- package/dist/chunks/json-elements-BAmNBZok.js.map +1 -0
- package/dist/chunks/ontology-export-Bab4eUA8.js +357 -0
- package/dist/chunks/ontology-export-Bab4eUA8.js.map +1 -0
- package/dist/chunks/{records-dbRkxwaq.js → records-CdlvL4RO.js} +298 -114
- package/dist/chunks/records-CdlvL4RO.js.map +1 -0
- package/dist/chunks/{text-Dr0Ifpag.js → text-DzXjAiTl.js} +29 -11
- package/dist/chunks/text-DzXjAiTl.js.map +1 -0
- package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
- package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
- package/dist/csv.js +952 -262
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +6 -3
- package/dist/cx2.js +2 -2
- package/dist/cys.js +6 -3
- package/dist/dot.js +1 -1
- package/dist/gexf.js +554 -122
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +344 -87
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +1105 -213
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -2
- package/dist/graphml.js.map +1 -1
- package/dist/json.js +3 -2
- package/dist/neo4j.js +565 -158
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +6 -3
- package/dist/pajek.js +1 -1
- package/dist/src/children.d.ts +18 -6
- package/dist/src/children.d.ts.map +1 -1
- package/dist/src/children.js +6 -3
- package/dist/src/children.js.map +1 -1
- package/dist/src/common/attributes.d.ts +29 -11
- package/dist/src/common/attributes.d.ts.map +1 -1
- package/dist/src/common/attributes.js +25 -7
- package/dist/src/common/attributes.js.map +1 -1
- package/dist/src/common/cell-budget.d.ts +9 -2
- package/dist/src/common/cell-budget.d.ts.map +1 -1
- package/dist/src/common/cell-budget.js +11 -3
- package/dist/src/common/cell-budget.js.map +1 -1
- package/dist/src/common/choose.d.ts +19 -0
- package/dist/src/common/choose.d.ts.map +1 -0
- package/dist/src/common/choose.js +72 -0
- package/dist/src/common/choose.js.map +1 -0
- package/dist/src/common/codes.d.ts +456 -66
- package/dist/src/common/codes.d.ts.map +1 -1
- package/dist/src/common/codes.js +458 -66
- package/dist/src/common/codes.js.map +1 -1
- package/dist/src/common/compare.d.ts +81 -0
- package/dist/src/common/compare.d.ts.map +1 -0
- package/dist/src/common/compare.js +394 -0
- package/dist/src/common/compare.js.map +1 -0
- package/dist/src/common/cx-export.d.ts +123 -0
- package/dist/src/common/cx-export.d.ts.map +1 -0
- package/dist/src/common/cx-export.js +334 -0
- package/dist/src/common/cx-export.js.map +1 -0
- package/dist/src/common/declared-types.d.ts +22 -2
- package/dist/src/common/declared-types.d.ts.map +1 -1
- package/dist/src/common/declared-types.js +21 -3
- package/dist/src/common/declared-types.js.map +1 -1
- package/dist/src/common/direction.d.ts +74 -50
- package/dist/src/common/direction.d.ts.map +1 -1
- package/dist/src/common/direction.js +47 -27
- package/dist/src/common/direction.js.map +1 -1
- package/dist/src/common/escape.d.ts +21 -9
- package/dist/src/common/escape.d.ts.map +1 -1
- package/dist/src/common/escape.js +39 -22
- package/dist/src/common/escape.js.map +1 -1
- package/dist/src/common/export.d.ts +144 -32
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +216 -42
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/format.d.ts +23 -1
- package/dist/src/common/format.d.ts.map +1 -1
- package/dist/src/common/format.js +26 -1
- package/dist/src/common/format.js.map +1 -1
- package/dist/src/common/ids.d.ts +9 -2
- package/dist/src/common/ids.d.ts.map +1 -1
- package/dist/src/common/ids.js +6 -2
- package/dist/src/common/ids.js.map +1 -1
- package/dist/src/common/input.d.ts +122 -28
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +890 -124
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +144 -20
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +869 -189
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/common/line-format.d.ts +90 -0
- package/dist/src/common/line-format.d.ts.map +1 -0
- package/dist/src/common/line-format.js +185 -0
- package/dist/src/common/line-format.js.map +1 -0
- package/dist/src/common/lists.d.ts +6 -1
- package/dist/src/common/lists.d.ts.map +1 -1
- package/dist/src/common/lists.js +3 -1
- package/dist/src/common/lists.js.map +1 -1
- package/dist/src/common/ontology-export.d.ts +167 -0
- package/dist/src/common/ontology-export.d.ts.map +1 -0
- package/dist/src/common/ontology-export.js +359 -0
- package/dist/src/common/ontology-export.js.map +1 -0
- package/dist/src/common/ontology.d.ts +25 -3
- package/dist/src/common/ontology.d.ts.map +1 -1
- package/dist/src/common/ontology.js +30 -9
- package/dist/src/common/ontology.js.map +1 -1
- package/dist/src/common/options.d.ts +62 -12
- package/dist/src/common/options.d.ts.map +1 -1
- package/dist/src/common/options.js +89 -11
- package/dist/src/common/options.js.map +1 -1
- package/dist/src/common/plural.d.ts +31 -0
- package/dist/src/common/plural.d.ts.map +1 -0
- package/dist/src/common/plural.js +46 -0
- package/dist/src/common/plural.js.map +1 -0
- package/dist/src/common/report.d.ts +72 -14
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +146 -22
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/common/temporal.d.ts +22 -5
- package/dist/src/common/temporal.d.ts.map +1 -1
- package/dist/src/common/temporal.js +13 -2
- package/dist/src/common/temporal.js.map +1 -1
- package/dist/src/common/text.d.ts +39 -23
- package/dist/src/common/text.d.ts.map +1 -1
- package/dist/src/common/text.js +51 -21
- package/dist/src/common/text.js.map +1 -1
- package/dist/src/common/weights.d.ts +37 -4
- package/dist/src/common/weights.d.ts.map +1 -1
- package/dist/src/common/weights.js +61 -2
- package/dist/src/common/weights.js.map +1 -1
- package/dist/src/common/writer.d.ts +19 -3
- package/dist/src/common/writer.d.ts.map +1 -1
- package/dist/src/common/writer.js +30 -2
- package/dist/src/common/writer.js.map +1 -1
- package/dist/src/common/xml.d.ts +125 -9
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +402 -85
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/common/zip.d.ts +44 -4
- package/dist/src/common/zip.d.ts.map +1 -1
- package/dist/src/common/zip.js +134 -5
- package/dist/src/common/zip.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts +80 -24
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +146 -33
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/csv/header.d.ts +38 -9
- package/dist/src/formats/csv/header.d.ts.map +1 -1
- package/dist/src/formats/csv/header.js +46 -10
- package/dist/src/formats/csv/header.js.map +1 -1
- package/dist/src/formats/csv/importer.d.ts +187 -37
- package/dist/src/formats/csv/importer.d.ts.map +1 -1
- package/dist/src/formats/csv/importer.js +835 -204
- package/dist/src/formats/csv/importer.js.map +1 -1
- package/dist/src/formats/csv/index.d.ts +100 -19
- package/dist/src/formats/csv/index.d.ts.map +1 -1
- package/dist/src/formats/csv/index.js +94 -21
- package/dist/src/formats/csv/index.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts +95 -10
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +333 -122
- package/dist/src/formats/csv/records.js.map +1 -1
- package/dist/src/formats/csv/values.d.ts +1 -0
- package/dist/src/formats/csv/values.d.ts.map +1 -1
- package/dist/src/formats/csv/values.js +1 -0
- package/dist/src/formats/csv/values.js.map +1 -1
- package/dist/src/formats/cx/exporter.d.ts +102 -0
- package/dist/src/formats/cx/exporter.d.ts.map +1 -0
- package/dist/src/formats/cx/exporter.js +1217 -0
- package/dist/src/formats/cx/exporter.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts +79 -32
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +682 -287
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/index.d.ts +4 -3
- package/dist/src/formats/cx/index.d.ts.map +1 -1
- package/dist/src/formats/cx/index.js +4 -3
- package/dist/src/formats/cx/index.js.map +1 -1
- package/dist/src/formats/cx2/exporter.d.ts +29 -11
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx2/exporter.js +39 -268
- package/dist/src/formats/cx2/exporter.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts +78 -28
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +227 -80
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/index.d.ts +2 -1
- package/dist/src/formats/cx2/index.d.ts.map +1 -1
- package/dist/src/formats/cx2/index.js +2 -1
- package/dist/src/formats/cx2/index.js.map +1 -1
- package/dist/src/formats/cys/constants.d.ts +66 -17
- package/dist/src/formats/cys/constants.d.ts.map +1 -1
- package/dist/src/formats/cys/constants.js +59 -18
- package/dist/src/formats/cys/constants.js.map +1 -1
- package/dist/src/formats/cys/exporter.d.ts +118 -0
- package/dist/src/formats/cys/exporter.d.ts.map +1 -0
- package/dist/src/formats/cys/exporter.js +1072 -0
- package/dist/src/formats/cys/exporter.js.map +1 -0
- package/dist/src/formats/cys/importer.d.ts +22 -8
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +510 -149
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/index.d.ts +4 -2
- package/dist/src/formats/cys/index.d.ts.map +1 -1
- package/dist/src/formats/cys/index.js +4 -2
- package/dist/src/formats/cys/index.js.map +1 -1
- package/dist/src/formats/cys/session.d.ts +46 -7
- package/dist/src/formats/cys/session.d.ts.map +1 -1
- package/dist/src/formats/cys/session.js +101 -27
- package/dist/src/formats/cys/session.js.map +1 -1
- package/dist/src/formats/cys/tables.d.ts +9 -2
- package/dist/src/formats/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +29 -7
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/dot/exporter.d.ts +42 -14
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +56 -29
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts +91 -29
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +190 -39
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +2 -1
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +2 -1
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/names.d.ts +44 -11
- package/dist/src/formats/dot/names.d.ts.map +1 -1
- package/dist/src/formats/dot/names.js +44 -11
- package/dist/src/formats/dot/names.js.map +1 -1
- package/dist/src/formats/dot/tokenizer.d.ts +9 -2
- package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
- package/dist/src/formats/dot/tokenizer.js +20 -5
- package/dist/src/formats/dot/tokenizer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts +46 -15
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +45 -15
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +87 -23
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +471 -90
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +84 -21
- package/dist/src/formats/gexf/index.d.ts.map +1 -1
- package/dist/src/formats/gexf/index.js +80 -23
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gexf/schema.d.ts +67 -15
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +59 -13
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts +69 -21
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +74 -29
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +116 -25
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +290 -61
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +87 -24
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +79 -26
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/syntax.d.ts +67 -18
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +110 -28
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/constants.d.ts +174 -44
- package/dist/src/formats/graphml/constants.d.ts.map +1 -1
- package/dist/src/formats/graphml/constants.js +165 -44
- package/dist/src/formats/graphml/constants.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts +17 -9
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +33 -12
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts +19 -7
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +466 -39
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/index.d.ts +2 -1
- package/dist/src/formats/graphml/index.d.ts.map +1 -1
- package/dist/src/formats/graphml/index.js +2 -1
- package/dist/src/formats/graphml/index.js.map +1 -1
- package/dist/src/formats/graphml/tree.d.ts +6 -2
- package/dist/src/formats/graphml/tree.d.ts.map +1 -1
- package/dist/src/formats/graphml/tree.js +6 -2
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +8 -3
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +36 -15
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +88 -24
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +109 -19
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts +134 -22
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +135 -54
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +173 -52
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +899 -220
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/index.d.ts +3 -2
- package/dist/src/formats/json/index.d.ts.map +1 -1
- package/dist/src/formats/json/index.js +3 -2
- package/dist/src/formats/json/index.js.map +1 -1
- package/dist/src/formats/json/obographs-export.d.ts +68 -0
- package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
- package/dist/src/formats/json/obographs-export.js +941 -0
- package/dist/src/formats/json/obographs-export.js.map +1 -0
- package/dist/src/formats/json/obographs.d.ts +26 -0
- package/dist/src/formats/json/obographs.d.ts.map +1 -1
- package/dist/src/formats/json/obographs.js +297 -80
- package/dist/src/formats/json/obographs.js.map +1 -1
- package/dist/src/formats/neo4j/exporter.d.ts +109 -21
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +239 -86
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/neo4j/header.d.ts +17 -4
- package/dist/src/formats/neo4j/header.d.ts.map +1 -1
- package/dist/src/formats/neo4j/header.js +36 -4
- package/dist/src/formats/neo4j/header.js.map +1 -1
- package/dist/src/formats/neo4j/importer.d.ts +107 -27
- package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
- package/dist/src/formats/neo4j/importer.js +415 -63
- package/dist/src/formats/neo4j/importer.js.map +1 -1
- package/dist/src/formats/neo4j/index.d.ts +73 -23
- package/dist/src/formats/neo4j/index.d.ts.map +1 -1
- package/dist/src/formats/neo4j/index.js +65 -25
- package/dist/src/formats/neo4j/index.js.map +1 -1
- package/dist/src/formats/obo/exporter.d.ts +150 -0
- package/dist/src/formats/obo/exporter.d.ts.map +1 -0
- package/dist/src/formats/obo/exporter.js +1736 -0
- package/dist/src/formats/obo/exporter.js.map +1 -0
- package/dist/src/formats/obo/importer.d.ts +95 -19
- package/dist/src/formats/obo/importer.d.ts.map +1 -1
- package/dist/src/formats/obo/importer.js +475 -104
- package/dist/src/formats/obo/importer.js.map +1 -1
- package/dist/src/formats/obo/index.d.ts +6 -3
- package/dist/src/formats/obo/index.d.ts.map +1 -1
- package/dist/src/formats/obo/index.js +6 -3
- package/dist/src/formats/obo/index.js.map +1 -1
- package/dist/src/formats/obo/syntax.d.ts +108 -4
- package/dist/src/formats/obo/syntax.d.ts.map +1 -1
- package/dist/src/formats/obo/syntax.js +211 -34
- package/dist/src/formats/obo/syntax.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts +54 -16
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +67 -35
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +84 -22
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +303 -83
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +2 -1
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js +2 -1
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +77 -14
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +186 -54
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts +1 -0
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
- package/dist/src/formats/xgmml/columns.js +4 -0
- package/dist/src/formats/xgmml/columns.js.map +1 -1
- package/dist/src/formats/xgmml/constants.d.ts +186 -56
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
- package/dist/src/formats/xgmml/constants.js +181 -57
- package/dist/src/formats/xgmml/constants.js.map +1 -1
- package/dist/src/formats/xgmml/document.d.ts +65 -11
- package/dist/src/formats/xgmml/document.d.ts.map +1 -1
- package/dist/src/formats/xgmml/document.js +157 -28
- package/dist/src/formats/xgmml/document.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +61 -3
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +129 -26
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts +13 -6
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +21 -22
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts +33 -12
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +35 -72
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/formats/xgmml/index.d.ts +1 -0
- package/dist/src/formats/xgmml/index.d.ts.map +1 -1
- package/dist/src/formats/xgmml/index.js +1 -0
- package/dist/src/formats/xgmml/index.js.map +1 -1
- package/dist/src/formats/xgmml/values.d.ts +8 -1
- package/dist/src/formats/xgmml/values.d.ts.map +1 -1
- package/dist/src/formats/xgmml/values.js +8 -3
- package/dist/src/formats/xgmml/values.js.map +1 -1
- package/dist/src/index.d.ts +23 -18
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +28 -16
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts +478 -92
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +807 -88
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sniff.d.ts +61 -19
- package/dist/src/sniff.d.ts.map +1 -1
- package/dist/src/sniff.js +121 -29
- package/dist/src/sniff.js.map +1 -1
- package/dist/src/types.d.ts +362 -112
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +28 -7
- package/dist/src/types.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/docs/samples/README.md +25 -0
- package/docs/samples/got-edges.csv +353 -0
- package/docs/samples/got-network.graphml +1384 -0
- package/docs/samples/got-nodes.csv +108 -0
- package/docs/samples/got.cx +930 -0
- package/docs/samples/got.cx2 +465 -0
- package/docs/samples/got.gexf +471 -0
- package/docs/samples/got.gml +2650 -0
- package/docs/samples/got.json +2546 -0
- package/docs/samples/got.net +461 -0
- package/docs/samples/movies-nodes.csv +9 -0
- package/docs/samples/movies-rels.csv +8 -0
- package/docs/samples/networks.cys +0 -0
- package/docs/samples/proteins.xgmml +9 -0
- package/docs/samples/teams.gv +24 -0
- package/docs/samples/vehicles.obo +25 -0
- package/package.json +9 -4
- package/src/children.ts +18 -6
- package/src/common/attributes.ts +29 -11
- package/src/common/cell-budget.ts +11 -3
- package/src/common/choose.ts +89 -0
- package/src/common/codes.ts +490 -66
- package/src/common/compare.ts +472 -0
- package/src/common/cx-export.ts +432 -0
- package/src/common/declared-types.ts +40 -6
- package/src/common/direction.ts +78 -51
- package/src/common/escape.ts +39 -22
- package/src/common/export.ts +284 -47
- package/src/common/format.ts +30 -1
- package/src/common/ids.ts +14 -3
- package/src/common/input.ts +1057 -134
- package/src/common/json-elements.ts +1035 -199
- package/src/common/line-format.ts +249 -0
- package/src/common/lists.ts +7 -2
- package/src/common/ontology-export.ts +461 -0
- package/src/common/ontology.ts +31 -9
- package/src/common/options.ts +110 -15
- package/src/common/plural.ts +49 -0
- package/src/common/report.ts +168 -25
- package/src/common/temporal.ts +22 -5
- package/src/common/text.ts +62 -23
- package/src/common/weights.ts +74 -4
- package/src/common/writer.ts +37 -3
- package/src/common/xml.ts +479 -90
- package/src/common/zip.ts +169 -7
- package/src/formats/csv/exporter.ts +202 -47
- package/src/formats/csv/header.ts +50 -11
- package/src/formats/csv/importer.ts +1133 -245
- package/src/formats/csv/index.ts +106 -19
- package/src/formats/csv/records.ts +396 -122
- package/src/formats/csv/values.ts +1 -0
- package/src/formats/cx/exporter.ts +1483 -0
- package/src/formats/cx/importer.ts +890 -302
- package/src/formats/cx/index.ts +4 -3
- package/src/formats/cx2/exporter.ts +62 -339
- package/src/formats/cx2/importer.ts +318 -87
- package/src/formats/cx2/index.ts +2 -1
- package/src/formats/cys/constants.ts +62 -17
- package/src/formats/cys/exporter.ts +1368 -0
- package/src/formats/cys/importer.ts +659 -157
- package/src/formats/cys/index.ts +4 -2
- package/src/formats/cys/session.ts +142 -34
- package/src/formats/cys/tables.ts +47 -9
- package/src/formats/dot/exporter.ts +83 -37
- package/src/formats/dot/importer.ts +248 -54
- package/src/formats/dot/index.ts +2 -1
- package/src/formats/dot/names.ts +44 -11
- package/src/formats/dot/tokenizer.ts +25 -6
- package/src/formats/gexf/exporter.ts +57 -18
- package/src/formats/gexf/importer.ts +636 -105
- package/src/formats/gexf/index.ts +90 -21
- package/src/formats/gexf/schema.ts +67 -15
- package/src/formats/gml/exporter.ts +90 -36
- package/src/formats/gml/importer.ts +388 -67
- package/src/formats/gml/index.ts +85 -24
- package/src/formats/gml/syntax.ts +113 -28
- package/src/formats/graphml/constants.ts +178 -44
- package/src/formats/graphml/exporter.ts +52 -18
- package/src/formats/graphml/importer.ts +640 -60
- package/src/formats/graphml/index.ts +2 -1
- package/src/formats/graphml/tree.ts +6 -2
- package/src/formats/graphml/yfiles.ts +37 -15
- package/src/formats/json/dialect.ts +128 -29
- package/src/formats/json/exporter.ts +205 -68
- package/src/formats/json/importer.ts +1163 -253
- package/src/formats/json/index.ts +3 -1
- package/src/formats/json/obographs-export.ts +1197 -0
- package/src/formats/json/obographs.ts +353 -92
- package/src/formats/neo4j/exporter.ts +321 -102
- package/src/formats/neo4j/header.ts +44 -6
- package/src/formats/neo4j/importer.ts +512 -73
- package/src/formats/neo4j/index.ts +75 -23
- package/src/formats/obo/exporter.ts +2210 -0
- package/src/formats/obo/importer.ts +622 -109
- package/src/formats/obo/index.ts +6 -3
- package/src/formats/obo/syntax.ts +232 -37
- package/src/formats/pajek/exporter.ts +90 -42
- package/src/formats/pajek/importer.ts +407 -93
- package/src/formats/pajek/index.ts +2 -1
- package/src/formats/pajek/syntax.ts +216 -55
- package/src/formats/xgmml/columns.ts +10 -0
- package/src/formats/xgmml/constants.ts +183 -56
- package/src/formats/xgmml/document.ts +212 -34
- package/src/formats/xgmml/emit.ts +175 -34
- package/src/formats/xgmml/exporter.ts +36 -28
- package/src/formats/xgmml/importer.ts +64 -86
- package/src/formats/xgmml/index.ts +1 -0
- package/src/formats/xgmml/values.ts +12 -4
- package/src/index.ts +81 -11
- package/src/registry.ts +1121 -135
- package/src/sniff.ts +163 -32
- package/src/types.ts +385 -114
- package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
- package/dist/chunks/export-Bh60Dv-n.js +0 -582
- package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
- package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
- package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
- package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
- package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
- package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
- package/dist/chunks/importer-DET1tg6s.js.map +0 -1
- package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
- package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
- package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
- package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
- package/dist/chunks/importer-eUREhBGj.js.map +0 -1
- package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
- package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
- package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
- package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
- package/dist/chunks/ontology-BnrJ4I98.js +0 -113
- package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
- package/dist/chunks/records-dbRkxwaq.js.map +0 -1
- package/dist/chunks/report-B1z4WT9e.js +0 -2372
- package/dist/chunks/report-B1z4WT9e.js.map +0 -1
- package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
- package/dist/chunks/weights-Dzba96G3.js +0 -176
- package/dist/chunks/weights-Dzba96G3.js.map +0 -1
- package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
|
@@ -23,14 +23,21 @@ import {
|
|
|
23
23
|
PLACEHOLDER_COLUMN,
|
|
24
24
|
synonymScopeOf,
|
|
25
25
|
} from "../../common/ontology.js";
|
|
26
|
+
import { agree, plural } from "../../common/plural.js";
|
|
26
27
|
import { hasKey, isJsonObject } from "./dialect.js";
|
|
27
28
|
import { chosenGraph, type ImportContext, JSON_ISSUE, type JsonRecord } from "./importer.js";
|
|
28
29
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* The node keys the schema defines; any other key goes to `obo.unrecognized`.
|
|
32
|
+
* @category Plugin helpers
|
|
33
|
+
*/
|
|
34
|
+
export const NODE_KEYS: ReadonlySet<string> = new Set(["id", "lbl", "type", "propertyType", "meta"]);
|
|
31
35
|
|
|
32
|
-
/**
|
|
33
|
-
|
|
36
|
+
/**
|
|
37
|
+
* The `meta` keys mapped onto columns; any other key goes to `obo.unrecognized` as `meta.<key>`.
|
|
38
|
+
* @category Plugin helpers
|
|
39
|
+
*/
|
|
40
|
+
export const META_KEYS: ReadonlySet<string> = new Set([
|
|
34
41
|
"definition",
|
|
35
42
|
"comments",
|
|
36
43
|
"subsets",
|
|
@@ -40,23 +47,32 @@ const META_KEYS: ReadonlySet<string> = new Set([
|
|
|
40
47
|
"deprecated",
|
|
41
48
|
]);
|
|
42
49
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
50
|
+
/**
|
|
51
|
+
* The OBO frame type of an OBO Graphs node type.
|
|
52
|
+
* @category Plugin helpers
|
|
53
|
+
*/
|
|
54
|
+
export const FRAME_TYPES: Readonly<Record<string, string>> = Object.freeze({
|
|
45
55
|
CLASS: "Term",
|
|
46
56
|
INDIVIDUAL: "Instance",
|
|
47
57
|
PROPERTY: "Typedef",
|
|
48
58
|
});
|
|
49
59
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
60
|
+
/**
|
|
61
|
+
* The OBO name of the predicates OBO Graphs writes without an IRI.
|
|
62
|
+
* @category Plugin helpers
|
|
63
|
+
*/
|
|
64
|
+
export const BUILTIN_PREDICATES: Readonly<Record<string, string>> = Object.freeze({
|
|
52
65
|
is_a: "is_a",
|
|
53
66
|
subPropertyOf: "is_a",
|
|
54
67
|
type: "instance_of",
|
|
55
68
|
inverseOf: "inverse_of",
|
|
56
69
|
});
|
|
57
70
|
|
|
58
|
-
/**
|
|
59
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Predicates that relate two properties (metadata under typedefs "metadata").
|
|
73
|
+
* @category Plugin helpers
|
|
74
|
+
*/
|
|
75
|
+
export const PROPERTY_PREDICATES: ReadonlySet<string> = new Set(["subPropertyOf", "inverseOf"]);
|
|
60
76
|
|
|
61
77
|
/** Writes the OBO vocabulary columns, declaring each on first use. */
|
|
62
78
|
class ColumnWriter {
|
|
@@ -116,12 +132,27 @@ interface Vocabulary {
|
|
|
116
132
|
readonly id: (iri: string) => string;
|
|
117
133
|
/** A predicate as the relation name the edge column holds. */
|
|
118
134
|
readonly relation: (pred: string) => string;
|
|
119
|
-
/** Whether an IRI names a PROPERTY node. */
|
|
135
|
+
/** Whether an IRI names a PROPERTY node and no node of another type. */
|
|
120
136
|
readonly isProperty: (iri: string) => boolean;
|
|
121
|
-
/**
|
|
137
|
+
/** Whether an IRI names a node that is not a PROPERTY (a class, an individual). */
|
|
138
|
+
readonly isClass: (iri: string) => boolean;
|
|
139
|
+
/** The PROPERTY nodes kept as metadata, by IRI (a null-prototype record: an IRI may be `__proto__`). */
|
|
122
140
|
readonly properties: Record<string, unknown>;
|
|
141
|
+
/** The first id as written of each node id as read (two ids may meet only after IRI compaction). */
|
|
142
|
+
readonly written: Map<string, string>;
|
|
123
143
|
}
|
|
124
144
|
|
|
145
|
+
/** The axiom sections of an OBO Graphs graph, each an array (kept verbatim in the metadata). */
|
|
146
|
+
const AXIOM_KEYS: readonly string[] = [
|
|
147
|
+
"logicalDefinitionAxioms",
|
|
148
|
+
"equivalentNodesSets",
|
|
149
|
+
"domainRangeAxioms",
|
|
150
|
+
"propertyChainAxioms",
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
/** The edge keys the schema defines (`subj` is the README's outdated spelling of `sub`). */
|
|
154
|
+
const EDGE_KEYS: ReadonlySet<string> = new Set(["sub", "subj", "pred", "obj", "meta"]);
|
|
155
|
+
|
|
125
156
|
/**
|
|
126
157
|
* The id rule and the property table of one graph: PROPERTY nodes are found first, so an edge's
|
|
127
158
|
* predicate is named by the shorthand of the property it names wherever that property stands.
|
|
@@ -132,8 +163,13 @@ interface Vocabulary {
|
|
|
132
163
|
function vocabularyOf(nodes: readonly unknown[], oboIds: "curie" | "iri"): Vocabulary {
|
|
133
164
|
const shorthands = new Map<string, string>();
|
|
134
165
|
const propertyIds = new Set<string>();
|
|
166
|
+
const classIds = new Set<string>();
|
|
135
167
|
for (const node of nodes) {
|
|
136
|
-
if (!isJsonObject(node) || typeof node.id !== "string"
|
|
168
|
+
if (!isJsonObject(node) || typeof node.id !== "string") {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (node.type !== "PROPERTY") {
|
|
172
|
+
classIds.add(node.id);
|
|
137
173
|
continue;
|
|
138
174
|
}
|
|
139
175
|
propertyIds.add(node.id);
|
|
@@ -146,8 +182,10 @@ function vocabularyOf(nodes: readonly unknown[], oboIds: "curie" | "iri"): Vocab
|
|
|
146
182
|
return {
|
|
147
183
|
id: (iri) => (oboIds === "curie" ? (shorthands.get(iri) ?? compactOboIri(iri)) : iri),
|
|
148
184
|
relation: (pred) => BUILTIN_PREDICATES[pred] ?? shorthands.get(pred) ?? compact(pred),
|
|
149
|
-
isProperty: (iri) => propertyIds.has(iri),
|
|
150
|
-
|
|
185
|
+
isProperty: (iri) => propertyIds.has(iri) && !classIds.has(iri),
|
|
186
|
+
isClass: (iri) => classIds.has(iri),
|
|
187
|
+
properties: Object.create(null) as Record<string, unknown>,
|
|
188
|
+
written: new Map(),
|
|
151
189
|
};
|
|
152
190
|
}
|
|
153
191
|
|
|
@@ -155,43 +193,73 @@ function vocabularyOf(nodes: readonly unknown[], oboIds: "curie" | "iri"): Vocab
|
|
|
155
193
|
interface PropertyValue {
|
|
156
194
|
readonly pred: string;
|
|
157
195
|
readonly val: string;
|
|
196
|
+
readonly meta?: unknown;
|
|
158
197
|
}
|
|
159
198
|
|
|
160
199
|
/**
|
|
161
|
-
* The well-formed `basicPropertyValues` of a node's meta
|
|
200
|
+
* The well-formed `basicPropertyValues` of a node's meta, each malformed entry reported when a
|
|
201
|
+
* context is given (the vocabulary pre-pass reads them silently; writeMeta reports them).
|
|
162
202
|
* @param meta - the node's meta, or anything
|
|
203
|
+
* @param ctx - the context to report through, or null
|
|
204
|
+
* @param element - the node's name in messages
|
|
163
205
|
* @returns the entries with a string pred and val
|
|
164
206
|
*/
|
|
165
|
-
function basicValues(meta: unknown): PropertyValue[] {
|
|
166
|
-
if (!isJsonObject(meta) ||
|
|
207
|
+
function basicValues(meta: unknown, ctx: ImportContext | null = null, element = ""): PropertyValue[] {
|
|
208
|
+
if (!isJsonObject(meta) || meta.basicPropertyValues === undefined || meta.basicPropertyValues === null) {
|
|
167
209
|
return [];
|
|
168
210
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
211
|
+
const path = `${element}.meta.basicPropertyValues`;
|
|
212
|
+
if (!Array.isArray(meta.basicPropertyValues)) {
|
|
213
|
+
if (ctx !== null) {
|
|
214
|
+
badValue(ctx, `${path} must be an array; it is dropped`, path);
|
|
215
|
+
}
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
const out: PropertyValue[] = [];
|
|
219
|
+
meta.basicPropertyValues.forEach((pv: unknown, j: number) => {
|
|
220
|
+
if (isJsonObject(pv) && typeof pv.pred === "string" && typeof pv.val === "string") {
|
|
221
|
+
out.push(pv as unknown as PropertyValue);
|
|
222
|
+
} else if (ctx !== null) {
|
|
223
|
+
badValue(ctx, `${path}[${j}] needs a string pred and a string val; it is dropped`, `${path}[${j}]`);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return out;
|
|
172
227
|
}
|
|
173
228
|
|
|
174
229
|
/**
|
|
175
|
-
* The strings of an array, or of an array of `{ val }` records
|
|
176
|
-
*
|
|
230
|
+
* The strings of an array, or of an array of `{ val }` records, each item that is neither
|
|
231
|
+
* reported (E_BAD_VALUE) and dropped, and a value that is not an array reported whole.
|
|
232
|
+
* @param ctx - the context
|
|
233
|
+
* @param value - the array, or anything (undefined and null: none)
|
|
234
|
+
* @param path - the field's path in messages
|
|
177
235
|
* @returns the strings
|
|
178
236
|
*/
|
|
179
|
-
function strings(value: unknown): string[] {
|
|
237
|
+
function strings(ctx: ImportContext, value: unknown, path: string): string[] {
|
|
238
|
+
if (value === undefined || value === null) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
180
241
|
if (!Array.isArray(value)) {
|
|
242
|
+
badValue(ctx, `${path} must be an array; it is dropped`, path);
|
|
181
243
|
return [];
|
|
182
244
|
}
|
|
183
|
-
|
|
245
|
+
const out: string[] = [];
|
|
246
|
+
value.forEach((item: unknown, j: number) => {
|
|
184
247
|
if (typeof item === "string") {
|
|
185
|
-
|
|
248
|
+
out.push(item);
|
|
249
|
+
} else if (isJsonObject(item) && typeof item.val === "string") {
|
|
250
|
+
out.push(item.val);
|
|
251
|
+
} else {
|
|
252
|
+
badValue(ctx, `${path}[${j}] is not a string or a { val } record; it is dropped`, `${path}[${j}]`);
|
|
186
253
|
}
|
|
187
|
-
return isJsonObject(item) && typeof item.val === "string" ? [item.val] : [];
|
|
188
254
|
});
|
|
255
|
+
return out;
|
|
189
256
|
}
|
|
190
257
|
|
|
191
258
|
/**
|
|
192
259
|
* Read the chosen graph of an OBO Graphs document into the sink.
|
|
193
260
|
* @param ctx - the import context
|
|
194
261
|
* @param root - the document
|
|
262
|
+
* @category Plugin helpers
|
|
195
263
|
*/
|
|
196
264
|
export function importObographs(ctx: ImportContext, root: JsonRecord): void {
|
|
197
265
|
const graph = chosenGraph(ctx, root, "OBO Graphs");
|
|
@@ -212,6 +280,12 @@ export function importObographs(ctx: ImportContext, root: JsonRecord): void {
|
|
|
212
280
|
graphMeta[key] = graph[key];
|
|
213
281
|
}
|
|
214
282
|
}
|
|
283
|
+
for (const key of AXIOM_KEYS) {
|
|
284
|
+
const axioms = graph[key];
|
|
285
|
+
if (axioms !== undefined && axioms !== null && !Array.isArray(axioms)) {
|
|
286
|
+
badValue(ctx, `the graph's ${key} must be an array; it is kept as written`, key);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
215
289
|
const document: JsonRecord = {};
|
|
216
290
|
for (const key of Object.keys(root)) {
|
|
217
291
|
if (key !== "graphs") {
|
|
@@ -274,33 +348,44 @@ function readNode(
|
|
|
274
348
|
ctx.badElement("node", element);
|
|
275
349
|
return;
|
|
276
350
|
}
|
|
277
|
-
if (typeof record.id !== "string") {
|
|
351
|
+
if (typeof record.id !== "string" || record.id.length === 0) {
|
|
278
352
|
if (record.id === undefined) {
|
|
279
353
|
ctx.coerceId(undefined, element);
|
|
354
|
+
} else if (record.id === "") {
|
|
355
|
+
ctx.report.error("missing-value", JSON_ISSUE.MISSING_ID, `${element} has an empty id; it is skipped`, {
|
|
356
|
+
element,
|
|
357
|
+
});
|
|
280
358
|
} else {
|
|
281
359
|
badValue(ctx, `${element}.id must be a string; the node is skipped`);
|
|
282
360
|
}
|
|
283
361
|
ctx.countSkipped("node");
|
|
284
362
|
return;
|
|
285
363
|
}
|
|
364
|
+
if (typeof record.type === "string" && FRAME_TYPES[record.type] === undefined) {
|
|
365
|
+
ctx.report.warnOnce(
|
|
366
|
+
"unsupported",
|
|
367
|
+
JSON_ISSUE.UNKNOWN_ELEMENT,
|
|
368
|
+
`${element}: node type ${JSON.stringify(record.type)} is not CLASS, INDIVIDUAL or PROPERTY; kept as written`,
|
|
369
|
+
{ element: record.type },
|
|
370
|
+
`${JSON_ISSUE.UNKNOWN_ELEMENT}:type:${record.type}`,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
286
373
|
if (record.type === "PROPERTY" && ctx.json.typedefs === "metadata") {
|
|
287
|
-
|
|
288
|
-
const entry: JsonRecord = {};
|
|
289
|
-
for (const [key, value] of Object.entries({
|
|
290
|
-
lbl: record.lbl,
|
|
291
|
-
propertyType: record.propertyType,
|
|
292
|
-
shorthand,
|
|
293
|
-
meta: record.meta,
|
|
294
|
-
})) {
|
|
295
|
-
if (value !== undefined) {
|
|
296
|
-
entry[key] = value;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
vocabulary.properties[record.id] = entry;
|
|
374
|
+
readProperty(ctx, vocabulary, record, record.id, element);
|
|
300
375
|
return;
|
|
301
376
|
}
|
|
302
|
-
const
|
|
303
|
-
const
|
|
377
|
+
const compacted = vocabulary.id(record.id);
|
|
378
|
+
const id = ctx.coerceId(compacted, element);
|
|
379
|
+
// two ids that differ only by IRI compaction (the PURL and its CURIE) meet here
|
|
380
|
+
const earlier = vocabulary.written.get(compacted);
|
|
381
|
+
if (earlier === undefined) {
|
|
382
|
+
vocabulary.written.set(compacted, record.id);
|
|
383
|
+
}
|
|
384
|
+
const why =
|
|
385
|
+
earlier === undefined || earlier === record.id
|
|
386
|
+
? ""
|
|
387
|
+
: ` (${earlier} and ${record.id} meet only after IRI compaction; oboIds "iri" keeps them apart)`;
|
|
388
|
+
const row = id === null ? -1 : ctx.pushNode(id, element, why);
|
|
304
389
|
if (row < 0) {
|
|
305
390
|
return;
|
|
306
391
|
}
|
|
@@ -311,6 +396,45 @@ function readNode(
|
|
|
311
396
|
}
|
|
312
397
|
}
|
|
313
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Keep a PROPERTY node in the metadata (typedefs "metadata"), the first of a repeated id.
|
|
401
|
+
* @param ctx - the context
|
|
402
|
+
* @param vocabulary - the graph's vocabulary
|
|
403
|
+
* @param record - the node record
|
|
404
|
+
* @param iri - its id
|
|
405
|
+
* @param element - its name in messages
|
|
406
|
+
*/
|
|
407
|
+
function readProperty(
|
|
408
|
+
ctx: ImportContext,
|
|
409
|
+
vocabulary: Vocabulary,
|
|
410
|
+
record: JsonRecord,
|
|
411
|
+
iri: string,
|
|
412
|
+
element: string,
|
|
413
|
+
): void {
|
|
414
|
+
if (Object.hasOwn(vocabulary.properties, iri)) {
|
|
415
|
+
ctx.report.warning(
|
|
416
|
+
"merged",
|
|
417
|
+
JSON_ISSUE.DUPLICATE_NODE,
|
|
418
|
+
`${element}: property ${JSON.stringify(iri)} is declared again; the first declaration is kept`,
|
|
419
|
+
{ element },
|
|
420
|
+
);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
const shorthand = vocabulary.id(iri) === iri ? undefined : vocabulary.id(iri);
|
|
424
|
+
const entry: JsonRecord = {};
|
|
425
|
+
for (const [key, value] of Object.entries({
|
|
426
|
+
lbl: record.lbl,
|
|
427
|
+
propertyType: record.propertyType,
|
|
428
|
+
shorthand,
|
|
429
|
+
meta: record.meta,
|
|
430
|
+
})) {
|
|
431
|
+
if (value !== undefined) {
|
|
432
|
+
entry[key] = value;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
vocabulary.properties[iri] = entry;
|
|
436
|
+
}
|
|
437
|
+
|
|
314
438
|
/**
|
|
315
439
|
* Write a node's fields and meta onto the OBO columns.
|
|
316
440
|
* @param ctx - the context
|
|
@@ -347,7 +471,7 @@ function writeNode(
|
|
|
347
471
|
}
|
|
348
472
|
const { meta } = record;
|
|
349
473
|
if (isJsonObject(meta)) {
|
|
350
|
-
writeMeta(columns, vocabulary, meta, row, unrecognized);
|
|
474
|
+
writeMeta(ctx, columns, vocabulary, meta, row, unrecognized, element);
|
|
351
475
|
} else if (meta !== undefined && meta !== null) {
|
|
352
476
|
badValue(ctx, `${element}.meta must be an object`);
|
|
353
477
|
}
|
|
@@ -358,53 +482,64 @@ function writeNode(
|
|
|
358
482
|
|
|
359
483
|
/**
|
|
360
484
|
* Write a node's `meta` onto the OBO columns (design 4.6): definition, comments, subsets, xrefs,
|
|
361
|
-
* synonyms, deprecated, and the basicPropertyValues mapped back to the OBO tag they came from.
|
|
485
|
+
* synonyms, deprecated, and the basicPropertyValues mapped back to the OBO tag they came from. A
|
|
486
|
+
* field of the wrong JSON type is reported and dropped; a nested `meta` (axiom annotations) of
|
|
487
|
+
* a definition or a property value is kept in `obo.unrecognized`.
|
|
488
|
+
* @param ctx - the context
|
|
362
489
|
* @param columns - the column writer
|
|
363
490
|
* @param vocabulary - the graph's vocabulary
|
|
364
491
|
* @param meta - the meta record
|
|
365
492
|
* @param row - the node index
|
|
366
493
|
* @param unrecognized - where keys without a column go
|
|
494
|
+
* @param element - the node's name in messages
|
|
367
495
|
*/
|
|
368
496
|
function writeMeta(
|
|
497
|
+
ctx: ImportContext,
|
|
369
498
|
columns: ColumnWriter,
|
|
370
499
|
vocabulary: Vocabulary,
|
|
371
500
|
meta: JsonRecord,
|
|
372
501
|
row: number,
|
|
373
502
|
unrecognized: JsonRecord,
|
|
503
|
+
element: string,
|
|
374
504
|
): void {
|
|
505
|
+
const path = `${element}.meta`;
|
|
375
506
|
const { definition } = meta;
|
|
376
|
-
if (isJsonObject(definition)
|
|
377
|
-
|
|
378
|
-
|
|
507
|
+
if (isJsonObject(definition)) {
|
|
508
|
+
const xrefs = strings(ctx, definition.xrefs, `${path}.definition.xrefs`);
|
|
509
|
+
if (typeof definition.val === "string") {
|
|
510
|
+
columns.node("def", row, definition.val);
|
|
511
|
+
columns.node("def.xrefs", row, xrefs);
|
|
512
|
+
} else {
|
|
513
|
+
badValue(ctx, `${path}.definition has no string val; it is dropped`, `${path}.definition.val`);
|
|
514
|
+
}
|
|
515
|
+
if (definition.meta !== undefined) {
|
|
516
|
+
unrecognized["meta.definition.meta"] = definition.meta;
|
|
517
|
+
}
|
|
518
|
+
} else if (definition !== undefined && definition !== null) {
|
|
519
|
+
badValue(ctx, `${path}.definition must be an object with a val; it is dropped`, `${path}.definition`);
|
|
379
520
|
}
|
|
380
|
-
const comments = strings(meta.comments);
|
|
521
|
+
const comments = strings(ctx, meta.comments, `${path}.comments`);
|
|
381
522
|
if (comments.length > 0) {
|
|
382
523
|
columns.node("comment", row, comments.join("\n"));
|
|
383
524
|
}
|
|
384
|
-
const subsets = strings(meta.subsets).map((s) => vocabulary.id(s));
|
|
525
|
+
const subsets = strings(ctx, meta.subsets, `${path}.subsets`).map((s) => vocabulary.id(s));
|
|
385
526
|
if (subsets.length > 0) {
|
|
386
527
|
columns.node("subset", row, subsets);
|
|
387
528
|
}
|
|
388
|
-
const xrefs = strings(meta.xrefs);
|
|
529
|
+
const xrefs = strings(ctx, meta.xrefs, `${path}.xrefs`);
|
|
389
530
|
if (xrefs.length > 0) {
|
|
390
531
|
columns.node("xref", row, xrefs);
|
|
391
532
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
row,
|
|
396
|
-
meta.synonyms.filter(isJsonObject).map((s) => ({
|
|
397
|
-
text: typeof s.val === "string" ? s.val : null,
|
|
398
|
-
scope: typeof s.pred === "string" ? synonymScopeOf(s.pred) : null,
|
|
399
|
-
type: typeof s.synonymType === "string" ? vocabulary.id(s.synonymType) : null,
|
|
400
|
-
xrefs: strings(s.xrefs),
|
|
401
|
-
})),
|
|
402
|
-
);
|
|
533
|
+
const synonyms = synonymsOf(ctx, vocabulary, meta.synonyms, `${path}.synonyms`);
|
|
534
|
+
if (synonyms.length > 0) {
|
|
535
|
+
columns.node("synonym", row, synonyms);
|
|
403
536
|
}
|
|
404
537
|
if (typeof meta.deprecated === "boolean") {
|
|
405
538
|
columns.node("is_obsolete", row, meta.deprecated);
|
|
539
|
+
} else if (meta.deprecated !== undefined && meta.deprecated !== null) {
|
|
540
|
+
badValue(ctx, `${path}.deprecated must be a boolean; it is dropped`, `${path}.deprecated`);
|
|
406
541
|
}
|
|
407
|
-
writePropertyValues(columns, vocabulary,
|
|
542
|
+
writePropertyValues(ctx, columns, vocabulary, meta, row, unrecognized, element);
|
|
408
543
|
for (const key of Object.keys(meta)) {
|
|
409
544
|
if (!META_KEYS.has(key)) {
|
|
410
545
|
unrecognized[`meta.${key}`] = meta[key];
|
|
@@ -412,37 +547,118 @@ function writeMeta(
|
|
|
412
547
|
}
|
|
413
548
|
}
|
|
414
549
|
|
|
550
|
+
/**
|
|
551
|
+
* The synonyms of a node's meta as the OBO `synonym` items: each entry that is not an object or
|
|
552
|
+
* has no string val reported and dropped, a predicate that is not one of the four scopes kept with
|
|
553
|
+
* scope null (W_UNKNOWN_ELEMENT once per predicate), a nested `meta` kept on the item.
|
|
554
|
+
* @param ctx - the context
|
|
555
|
+
* @param vocabulary - the graph's vocabulary
|
|
556
|
+
* @param value - the `synonyms` field
|
|
557
|
+
* @param path - its path in messages
|
|
558
|
+
* @returns the items
|
|
559
|
+
*/
|
|
560
|
+
function synonymsOf(ctx: ImportContext, vocabulary: Vocabulary, value: unknown, path: string): JsonRecord[] {
|
|
561
|
+
if (value === undefined || value === null) {
|
|
562
|
+
return [];
|
|
563
|
+
}
|
|
564
|
+
if (!Array.isArray(value)) {
|
|
565
|
+
badValue(ctx, `${path} must be an array; it is dropped`, path);
|
|
566
|
+
return [];
|
|
567
|
+
}
|
|
568
|
+
const out: JsonRecord[] = [];
|
|
569
|
+
value.forEach((s: unknown, j: number) => {
|
|
570
|
+
const at = `${path}[${j}]`;
|
|
571
|
+
if (!isJsonObject(s)) {
|
|
572
|
+
badValue(ctx, `${at} is not an object; it is dropped`, at);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (typeof s.val !== "string") {
|
|
576
|
+
badValue(ctx, `${at} has no string val; it is dropped`, `${at}.val`);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const scope = typeof s.pred === "string" ? synonymScopeOf(s.pred) : null;
|
|
580
|
+
if (scope === null && typeof s.pred === "string") {
|
|
581
|
+
ctx.report.warnOnce(
|
|
582
|
+
"unsupported",
|
|
583
|
+
JSON_ISSUE.UNKNOWN_ELEMENT,
|
|
584
|
+
`${at}: synonym predicate ${JSON.stringify(s.pred)} is not one of the four scopes; kept with scope null`,
|
|
585
|
+
{ element: s.pred },
|
|
586
|
+
`${JSON_ISSUE.UNKNOWN_ELEMENT}:pred:${s.pred}`,
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
const item: JsonRecord = { text: s.val, scope, type: null, xrefs: strings(ctx, s.xrefs, `${at}.xrefs`) };
|
|
590
|
+
if (typeof s.synonymType === "string") {
|
|
591
|
+
item.type = vocabulary.id(s.synonymType);
|
|
592
|
+
} else if (s.synonymType !== undefined && s.synonymType !== null) {
|
|
593
|
+
badValue(ctx, `${at}.synonymType must be a string; it is dropped`, `${at}.synonymType`);
|
|
594
|
+
}
|
|
595
|
+
if (s.meta !== undefined) {
|
|
596
|
+
item.meta = s.meta;
|
|
597
|
+
}
|
|
598
|
+
out.push(item);
|
|
599
|
+
});
|
|
600
|
+
return out;
|
|
601
|
+
}
|
|
602
|
+
|
|
415
603
|
/**
|
|
416
604
|
* Write the basicPropertyValues: the ones an OBO tag maps to onto that tag's column (lists for
|
|
417
|
-
* alt_id, replaced_by, consider
|
|
605
|
+
* alt_id, replaced_by, consider; the first value of a single-valued tag, a repeat warned as the
|
|
606
|
+
* .obo importer warns it), the rest into `property_value`.
|
|
607
|
+
* @param ctx - the context
|
|
418
608
|
* @param columns - the column writer
|
|
419
609
|
* @param vocabulary - the graph's vocabulary
|
|
420
|
-
* @param
|
|
610
|
+
* @param meta - the node's meta
|
|
421
611
|
* @param row - the node index
|
|
612
|
+
* @param unrecognized - where the nested meta of a mapped value goes
|
|
613
|
+
* @param element - the node's name in messages
|
|
422
614
|
*/
|
|
423
615
|
function writePropertyValues(
|
|
616
|
+
ctx: ImportContext,
|
|
424
617
|
columns: ColumnWriter,
|
|
425
618
|
vocabulary: Vocabulary,
|
|
426
|
-
|
|
619
|
+
meta: JsonRecord,
|
|
427
620
|
row: number,
|
|
621
|
+
unrecognized: JsonRecord,
|
|
622
|
+
element: string,
|
|
428
623
|
): void {
|
|
429
624
|
const lists = new Map<string, string[]>();
|
|
625
|
+
const singles = new Map<string, string>();
|
|
430
626
|
const others: JsonRecord[] = [];
|
|
431
|
-
|
|
627
|
+
const values = basicValues(meta, ctx, element);
|
|
628
|
+
values.forEach(({ pred, val, meta: nested }, j) => {
|
|
432
629
|
const tag = OBOGRAPHS_PREDICATE_TAGS.get(pred);
|
|
433
630
|
if (tag === "shorthand") {
|
|
434
|
-
|
|
631
|
+
return;
|
|
435
632
|
}
|
|
436
633
|
if (tag === undefined) {
|
|
437
|
-
|
|
438
|
-
|
|
634
|
+
const item: JsonRecord = { relation: vocabulary.id(pred), value: val, datatype: null };
|
|
635
|
+
if (nested !== undefined) {
|
|
636
|
+
item.meta = nested;
|
|
637
|
+
}
|
|
638
|
+
others.push(item);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (nested !== undefined) {
|
|
642
|
+
unrecognized[`meta.basicPropertyValues[${j}].meta`] = nested;
|
|
643
|
+
}
|
|
644
|
+
if (OBO_NODE_COLUMNS[tag].dtype === "list") {
|
|
439
645
|
const list = lists.get(tag) ?? [];
|
|
440
646
|
list.push(tag === "alt_id" ? val : vocabulary.id(val));
|
|
441
647
|
lists.set(tag, list);
|
|
648
|
+
} else if (singles.get(tag) === val) {
|
|
649
|
+
// an identical value counts once, as an identical .obo clause does
|
|
650
|
+
} else if (singles.has(tag)) {
|
|
651
|
+
ctx.report.warning(
|
|
652
|
+
"validation-error",
|
|
653
|
+
JSON_ISSUE.DUPLICATE_ATTRIBUTE,
|
|
654
|
+
`${element}: a second ${tag} (${JSON.stringify(val)}); the first is kept`,
|
|
655
|
+
{ element: tag },
|
|
656
|
+
);
|
|
442
657
|
} else {
|
|
658
|
+
singles.set(tag, val);
|
|
443
659
|
columns.node(tag, row, val);
|
|
444
660
|
}
|
|
445
|
-
}
|
|
661
|
+
});
|
|
446
662
|
for (const [tag, list] of lists) {
|
|
447
663
|
columns.node(tag, row, list);
|
|
448
664
|
}
|
|
@@ -455,9 +671,60 @@ function writePropertyValues(
|
|
|
455
671
|
* Report a field of the wrong JSON type (the field is left unset, the element kept).
|
|
456
672
|
* @param ctx - the context
|
|
457
673
|
* @param message - what is wrong
|
|
674
|
+
* @param element - the field's path, when known
|
|
675
|
+
*/
|
|
676
|
+
function badValue(ctx: ImportContext, message: string, element?: string): void {
|
|
677
|
+
ctx.report.error(
|
|
678
|
+
"validation-error",
|
|
679
|
+
JSON_ISSUE.BAD_VALUE,
|
|
680
|
+
message,
|
|
681
|
+
element === undefined ? undefined : { element },
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* An edge's subject: `sub`, else the README's outdated `subj` (warned once), and a warning when
|
|
687
|
+
* both are present and differ; every key outside the schema warned once per key name.
|
|
688
|
+
* @param ctx - the context
|
|
689
|
+
* @param record - the edge record
|
|
690
|
+
* @param element - its name in messages
|
|
691
|
+
* @returns the subject value, unchecked
|
|
458
692
|
*/
|
|
459
|
-
function
|
|
460
|
-
|
|
693
|
+
function subjectOf(ctx: ImportContext, record: JsonRecord, element: string): unknown {
|
|
694
|
+
const { report } = ctx;
|
|
695
|
+
for (const key of Object.keys(record)) {
|
|
696
|
+
if (!EDGE_KEYS.has(key)) {
|
|
697
|
+
report.warnOnce(
|
|
698
|
+
"unsupported",
|
|
699
|
+
JSON_ISSUE.UNREAD_KEY,
|
|
700
|
+
`${element}: the key ${JSON.stringify(key)} is not part of an OBO Graphs edge; it is not read`,
|
|
701
|
+
{ element: `${element}.${key}` },
|
|
702
|
+
`${JSON_ISSUE.UNREAD_KEY}:edge:${key}`,
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (!hasKey(record, "sub")) {
|
|
707
|
+
if (hasKey(record, "subj")) {
|
|
708
|
+
report.warnOnce(
|
|
709
|
+
"coercion",
|
|
710
|
+
JSON_ISSUE.OBOGRAPHS_SUBJ,
|
|
711
|
+
`${element} uses the outdated key subj; read as sub`,
|
|
712
|
+
{
|
|
713
|
+
element,
|
|
714
|
+
},
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
return record.subj;
|
|
718
|
+
}
|
|
719
|
+
if (hasKey(record, "subj") && record.subj !== record.sub) {
|
|
720
|
+
report.warning(
|
|
721
|
+
"coercion",
|
|
722
|
+
JSON_ISSUE.OBOGRAPHS_SUBJ,
|
|
723
|
+
`${element} has both sub and the outdated subj, which differ; sub is read and subj ignored`,
|
|
724
|
+
{ element },
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
return record.sub;
|
|
461
728
|
}
|
|
462
729
|
|
|
463
730
|
/**
|
|
@@ -501,27 +768,19 @@ function readEdges(
|
|
|
501
768
|
ctx.badElement("edge", element);
|
|
502
769
|
continue;
|
|
503
770
|
}
|
|
504
|
-
const
|
|
505
|
-
if (subKey === "subj" && hasKey(record, "subj")) {
|
|
506
|
-
report.warnOnce(
|
|
507
|
-
"coercion",
|
|
508
|
-
JSON_ISSUE.OBOGRAPHS_SUBJ,
|
|
509
|
-
`${element} uses the outdated key subj; read as sub`,
|
|
510
|
-
{
|
|
511
|
-
element,
|
|
512
|
-
},
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
const sub = record[subKey];
|
|
771
|
+
const sub = subjectOf(ctx, record, element);
|
|
516
772
|
const { obj, pred } = record;
|
|
517
|
-
if (typeof sub !== "string" || typeof obj !== "string") {
|
|
518
|
-
ctx.missingEndpoint(element, typeof sub === "string" ? "obj" : "sub");
|
|
773
|
+
if (typeof sub !== "string" || typeof obj !== "string" || sub.length === 0 || obj.length === 0) {
|
|
774
|
+
ctx.missingEndpoint(element, typeof sub === "string" && sub.length > 0 ? "obj" : "sub");
|
|
519
775
|
continue;
|
|
520
776
|
}
|
|
777
|
+
// only an edge between two properties is property metadata; one that touches a class stays
|
|
521
778
|
const between =
|
|
522
|
-
(
|
|
523
|
-
|
|
524
|
-
|
|
779
|
+
(vocabulary.isProperty(sub) && vocabulary.isProperty(obj)) ||
|
|
780
|
+
(typeof pred === "string" &&
|
|
781
|
+
PROPERTY_PREDICATES.has(pred) &&
|
|
782
|
+
!vocabulary.isClass(sub) &&
|
|
783
|
+
!vocabulary.isClass(obj));
|
|
525
784
|
if (between && ctx.json.typedefs === "metadata") {
|
|
526
785
|
propertyEdges.push(record);
|
|
527
786
|
continue;
|
|
@@ -542,6 +801,8 @@ function readEdges(
|
|
|
542
801
|
}
|
|
543
802
|
if (isJsonObject(record.meta)) {
|
|
544
803
|
columns.edge("meta", edge, record.meta);
|
|
804
|
+
} else if (record.meta !== undefined && record.meta !== null) {
|
|
805
|
+
badValue(ctx, `${element}.meta must be an object; it is dropped`, `${element}.meta`);
|
|
545
806
|
}
|
|
546
807
|
} catch (err) {
|
|
547
808
|
ctx.skip(err, "edge", element);
|
|
@@ -551,11 +812,11 @@ function readEdges(
|
|
|
551
812
|
const shown = [...new Set(dangling)].slice(0, 5).join(", ");
|
|
552
813
|
const action = ctx.options.addMissingNodes
|
|
553
814
|
? "each became a placeholder node (graphty.placeholder)"
|
|
554
|
-
: `${dropped} edge(
|
|
815
|
+
: `${dropped} edge${plural(dropped)} to them ${agree(dropped, "was", "were")} dropped (addMissingNodes false)`;
|
|
555
816
|
report.warning(
|
|
556
817
|
"validation-error",
|
|
557
818
|
JSON_ISSUE.DANGLING_REFERENCE,
|
|
558
|
-
`${new Set(dangling).size} edge endpoint(
|
|
819
|
+
`${new Set(dangling).size} edge endpoint${plural(new Set(dangling).size)} missing from nodes: ${shown}; ${action}`,
|
|
559
820
|
{ element: dangling[0] },
|
|
560
821
|
);
|
|
561
822
|
}
|