@graphty/graph-io 0.3.25 → 0.3.26
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-BbJI55dx.js +56 -0
- package/dist/chunks/choose-BbJI55dx.js.map +1 -0
- package/dist/chunks/constants-BCsFsMj4.js +231 -0
- package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
- package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
- package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
- package/dist/chunks/export-BTI4yQgy.js +4333 -0
- package/dist/chunks/export-BTI4yQgy.js.map +1 -0
- package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
- package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
- package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
- package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
- package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
- package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
- package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
- package/dist/chunks/exporter-tne475KK.js.map +1 -0
- package/dist/chunks/importer-90YWhJoF.js +2811 -0
- package/dist/chunks/importer-90YWhJoF.js.map +1 -0
- package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
- package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
- package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
- package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
- package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
- package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
- package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
- package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
- package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
- package/dist/chunks/importer-DfVu6j59.js.map +1 -0
- package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
- package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
- package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
- package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
- package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
- package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
- package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
- package/dist/chunks/records-CQXT__mY.js.map +1 -0
- package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
- package/dist/chunks/text-DmcUs5_Q.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 +951 -261
- 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 +342 -85
- 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 +564 -157
- 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 +19 -1
- 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 +33 -17
- 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 +868 -188
- 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 +2 -0
- 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 +400 -83
- 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 +145 -32
- 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 +680 -285
- 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 +226 -79
- 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 +98 -24
- 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 +108 -26
- 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 +238 -85
- 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 +66 -34
- 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 +183 -51
- 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 +20 -21
- 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 +7 -2
- 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 +38 -4
- package/src/common/direction.ts +78 -51
- package/src/common/escape.ts +33 -17
- 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 +1034 -198
- package/src/common/line-format.ts +249 -0
- package/src/common/lists.ts +6 -1
- 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 +477 -88
- package/src/common/zip.ts +169 -7
- package/src/formats/csv/exporter.ts +201 -46
- 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 +888 -300
- package/src/formats/cx/index.ts +4 -3
- package/src/formats/cx2/exporter.ts +61 -338
- package/src/formats/cx2/importer.ts +317 -86
- 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 +139 -31
- 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 +111 -26
- 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 +320 -101
- 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 +89 -41
- package/src/formats/pajek/importer.ts +407 -93
- package/src/formats/pajek/index.ts +2 -1
- package/src/formats/pajek/syntax.ts +213 -52
- 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 +35 -27
- package/src/formats/xgmml/importer.ts +64 -86
- package/src/formats/xgmml/index.ts +1 -0
- package/src/formats/xgmml/values.ts +11 -3
- 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
|
@@ -19,19 +19,39 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { GraphFormatError, INVALID_INDEX, MAX_COUNT, } from "@graphty/graph-format";
|
|
21
21
|
import { declareAttribute, declareResolved, losesPrecision, parseDeclaredValue, PRECISION_CODE, takenIn, uniqueColumnName, } from "../../common/attributes.js";
|
|
22
|
+
import { overflowsToInfinity } from "../../common/declared-types.js";
|
|
22
23
|
import { DirectionResolver } from "../../common/direction.js";
|
|
23
24
|
import { IdCoercer } from "../../common/ids.js";
|
|
24
25
|
import { textChunks, throwIfAborted } from "../../common/input.js";
|
|
25
26
|
import { reportSinkOptions, reportUnusedOptions, resolveImportOptions, } from "../../common/options.js";
|
|
27
|
+
import { agree, plural } from "../../common/plural.js";
|
|
26
28
|
import { ImportReportBuilder } from "../../common/report.js";
|
|
27
29
|
import { isWeightField, parseWeightText } from "../../common/weights.js";
|
|
28
|
-
import { isWhitespace, localName, tokenizeXml, xmlDeclaredEncoding, XmlSyntaxError, } from "../../common/xml.js";
|
|
30
|
+
import { isWhitespace, localName, sniffXmlText, tokenizeXml, xmlDeclaredEncoding, XmlEmptyInputError, XmlSyntaxError, } from "../../common/xml.js";
|
|
29
31
|
import { EDGE_ID_COLUMN, EXTENSIONS, FORMAT, GRAPHML_ISSUE, GRAPHML_LOSS, GRAPHML_NAMESPACE, HYPEREDGE_HUB_COLUMN, LABEL_COLUMN, META_KEY, MIME_TYPES, ORIGINAL_ID_ATTRIBUTE, ORIGINAL_ID_COLUMN, PARENT_COLUMN, RESERVED_EDGE_NAMES, RESERVED_NODE_NAMES, SOURCE_PORT_COLUMN, TARGET_PORT_COLUMN, XSI_NAMESPACE, } from "./constants.js";
|
|
30
32
|
import { XmlTreeBuilder } from "./tree.js";
|
|
31
33
|
import { graphicsDecl, graphicsValues } from "./yfiles.js";
|
|
32
|
-
/** The XML attributes the importer reads on
|
|
34
|
+
/** The XML attributes the importer reads on each element; any other is reported (once per element and name). */
|
|
33
35
|
const GRAPH_ATTRIBUTES = new Set(["id", "edgedefault", "parse.nodes", "parse.edges"]);
|
|
34
36
|
const NODE_ATTRIBUTES = new Set(["id"]);
|
|
37
|
+
const KEY_ATTRIBUTES = new Set([
|
|
38
|
+
"id",
|
|
39
|
+
"for",
|
|
40
|
+
"attr.name",
|
|
41
|
+
"attr.type",
|
|
42
|
+
"name",
|
|
43
|
+
"type",
|
|
44
|
+
"yfiles.type",
|
|
45
|
+
]);
|
|
46
|
+
const DATA_ATTRIBUTES = new Set(["key"]);
|
|
47
|
+
const HYPEREDGE_ATTRIBUTES = new Set(["id"]);
|
|
48
|
+
const ENDPOINT_ATTRIBUTES = new Set(["node", "type"]);
|
|
49
|
+
const PORT_ATTRIBUTES = new Set(["name"]);
|
|
50
|
+
const NO_ATTRIBUTES = new Set();
|
|
51
|
+
/** Attributes the GraphML schema defines that the importer does not keep: reported as not kept, not as foreign. */
|
|
52
|
+
const SCHEMA_ATTRIBUTES = new Set(["id", "port", "parse.order", "parse.nodeids", "parse.edgeids"]);
|
|
53
|
+
/** Distinct unknown attribute names reported one by one per element kind; the rest are counted in one issue. */
|
|
54
|
+
const MAX_UNKNOWN_ATTRIBUTE_NAMES = 16;
|
|
35
55
|
const EDGE_ATTRIBUTES = new Set([
|
|
36
56
|
"id",
|
|
37
57
|
"source",
|
|
@@ -78,6 +98,10 @@ var Ctx;
|
|
|
78
98
|
Ctx[Ctx["Data"] = 8] = "Data";
|
|
79
99
|
Ctx[Ctx["Capture"] = 9] = "Capture";
|
|
80
100
|
Ctx[Ctx["Skip"] = 10] = "Skip";
|
|
101
|
+
/** A `<port>` (ports nest; their names are collected for the edge port check). */
|
|
102
|
+
Ctx[Ctx["Port"] = 11] = "Port";
|
|
103
|
+
/** Inside a `<graph>` held by an `<edge>`: dropped, its nodes and edges counted as skipped. */
|
|
104
|
+
Ctx[Ctx["Dropped"] = 12] = "Dropped";
|
|
81
105
|
})(Ctx || (Ctx = {}));
|
|
82
106
|
/**
|
|
83
107
|
* A growable bit set over node indices, marking the indices declared by a `<node>` element so a
|
|
@@ -133,6 +157,10 @@ class GraphmlReader {
|
|
|
133
157
|
this.nodes = [];
|
|
134
158
|
this.declared = new IndexFlags();
|
|
135
159
|
this.edgeIds = new Set();
|
|
160
|
+
/** The keys `<data>` referenced before any `<key>` declared them (E_GRAPHML_UNKNOWN_KEY). */
|
|
161
|
+
this.unknownKeyIds = new Set();
|
|
162
|
+
/** The ids of the edges waiting in {@link deferred}. */
|
|
163
|
+
this.deferredEdgeIds = new Set();
|
|
136
164
|
this.elementsSinceCheck = 0;
|
|
137
165
|
/** Mangled id text -> the original id restored from `graphty:originalId`, for edge endpoints. */
|
|
138
166
|
this.restored = new Map();
|
|
@@ -150,6 +178,9 @@ class GraphmlReader {
|
|
|
150
178
|
};
|
|
151
179
|
this.descTarget = null;
|
|
152
180
|
this.descText = "";
|
|
181
|
+
this.descLine = 0;
|
|
182
|
+
/** The keys of the graph-level `<data>` read so far, for the duplicate check. */
|
|
183
|
+
this.graphKeys = { keys: null };
|
|
153
184
|
this.description = null;
|
|
154
185
|
this.graphSeen = false;
|
|
155
186
|
this.graphId = null;
|
|
@@ -165,6 +196,24 @@ class GraphmlReader {
|
|
|
165
196
|
this.targetPortHandle = INVALID_INDEX;
|
|
166
197
|
this.parentHandle = INVALID_INDEX;
|
|
167
198
|
this.hubHandle = INVALID_INDEX;
|
|
199
|
+
/** The hub nodes of star-expanded hyperedges, so a later `<node>` of the same id is reported as a clash. */
|
|
200
|
+
this.hubs = new IndexFlags();
|
|
201
|
+
/** Edges and hyperedges whose endpoints were not declared yet under addMissingNodes: false, added at the end. */
|
|
202
|
+
this.deferred = [];
|
|
203
|
+
/** The ids of the `<graph>` elements read so far, for the endpoint-names-a-graph check. */
|
|
204
|
+
this.graphIds = new Set();
|
|
205
|
+
/** How many top-level `<graph>` elements were opened. */
|
|
206
|
+
this.topGraphs = 0;
|
|
207
|
+
/** The namespace of the `<graphml>` root (children in it are GraphML even when it is not GraphML's). */
|
|
208
|
+
this.rootNs = GRAPHML_NAMESPACE;
|
|
209
|
+
/** Whether a graph-level `<desc>` was kept, so a second one is reported. */
|
|
210
|
+
this.graphDescSeen = false;
|
|
211
|
+
/** Unknown attribute names reported per element kind, and how many more were not listed. */
|
|
212
|
+
this.unknownNames = new Map();
|
|
213
|
+
this.unknownOverflow = new Map();
|
|
214
|
+
/** The port names each node declares, and the ports edges reference, checked at the end. */
|
|
215
|
+
this.ports = new Map();
|
|
216
|
+
this.portRefs = [];
|
|
168
217
|
this.sink = sink;
|
|
169
218
|
this.report = report;
|
|
170
219
|
this.options = options;
|
|
@@ -178,8 +227,9 @@ class GraphmlReader {
|
|
|
178
227
|
* @param name - the element name
|
|
179
228
|
* @param attrs - its attributes
|
|
180
229
|
* @param line - the line
|
|
230
|
+
* @param ns - the element's namespace (null: an undeclared prefix)
|
|
181
231
|
*/
|
|
182
|
-
start(name, attrs, line) {
|
|
232
|
+
start(name, attrs, line, ns = "") {
|
|
183
233
|
const parent = this.ctx.length === 0 ? null : this.ctx[this.ctx.length - 1];
|
|
184
234
|
switch (parent) {
|
|
185
235
|
case Ctx.Capture:
|
|
@@ -193,10 +243,18 @@ class GraphmlReader {
|
|
|
193
243
|
case Ctx.Default:
|
|
194
244
|
this.captureStart(name, attrs);
|
|
195
245
|
return;
|
|
246
|
+
case Ctx.Dropped:
|
|
247
|
+
this.dropStart(localName(name));
|
|
248
|
+
return;
|
|
196
249
|
default:
|
|
197
250
|
break;
|
|
198
251
|
}
|
|
199
252
|
const local = localName(name);
|
|
253
|
+
if (parent !== null && ns !== GRAPHML_NAMESPACE && ns !== "" && ns !== this.rootNs) {
|
|
254
|
+
// a vendor element whose local name happens to be node, edge or data is not GraphML
|
|
255
|
+
this.unknownElement(name, line);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
200
258
|
switch (parent) {
|
|
201
259
|
case null:
|
|
202
260
|
if (local !== "graphml") {
|
|
@@ -204,6 +262,13 @@ class GraphmlReader {
|
|
|
204
262
|
line,
|
|
205
263
|
});
|
|
206
264
|
}
|
|
265
|
+
if (ns !== GRAPHML_NAMESPACE && ns !== "") {
|
|
266
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.NAMESPACE, ns === null
|
|
267
|
+
? `the root <${name}> uses an undeclared prefix; read as GraphML`
|
|
268
|
+
: `the root <${name}> is in the namespace ${JSON.stringify(ns)}, not ${GRAPHML_NAMESPACE}; read as GraphML`, { line, element: ns });
|
|
269
|
+
}
|
|
270
|
+
this.rootNs = ns;
|
|
271
|
+
this.reportUnreadAttributes("graphml", attrs, NO_ATTRIBUTES, line);
|
|
207
272
|
this.readRoot(attrs);
|
|
208
273
|
this.ctx.push(Ctx.Graphml);
|
|
209
274
|
return;
|
|
@@ -211,7 +276,7 @@ class GraphmlReader {
|
|
|
211
276
|
this.startInGraphml(name, local, attrs, line);
|
|
212
277
|
return;
|
|
213
278
|
case Ctx.Key:
|
|
214
|
-
this.startInKey(name, local, line);
|
|
279
|
+
this.startInKey(name, local, attrs, line);
|
|
215
280
|
return;
|
|
216
281
|
case Ctx.Graph:
|
|
217
282
|
this.startInGraph(name, local, attrs, line);
|
|
@@ -225,6 +290,9 @@ class GraphmlReader {
|
|
|
225
290
|
case Ctx.Hyperedge:
|
|
226
291
|
this.startInHyperedge(name, local, attrs, line);
|
|
227
292
|
return;
|
|
293
|
+
case Ctx.Port:
|
|
294
|
+
this.startInPort(name, local, attrs, line);
|
|
295
|
+
return;
|
|
228
296
|
default:
|
|
229
297
|
this.unknownElement(name, line);
|
|
230
298
|
}
|
|
@@ -242,6 +310,8 @@ class GraphmlReader {
|
|
|
242
310
|
return;
|
|
243
311
|
case Ctx.Skip:
|
|
244
312
|
case Ctx.Graphml:
|
|
313
|
+
case Ctx.Port:
|
|
314
|
+
case Ctx.Dropped:
|
|
245
315
|
case undefined:
|
|
246
316
|
return;
|
|
247
317
|
case Ctx.Desc:
|
|
@@ -266,7 +336,7 @@ class GraphmlReader {
|
|
|
266
336
|
this.finishHyperedge();
|
|
267
337
|
return;
|
|
268
338
|
case Ctx.Graph:
|
|
269
|
-
this.
|
|
339
|
+
this.finishGraph();
|
|
270
340
|
return;
|
|
271
341
|
default: {
|
|
272
342
|
const value = ctx;
|
|
@@ -298,6 +368,7 @@ class GraphmlReader {
|
|
|
298
368
|
this.descText += text;
|
|
299
369
|
return;
|
|
300
370
|
case Ctx.Skip:
|
|
371
|
+
case Ctx.Dropped:
|
|
301
372
|
return;
|
|
302
373
|
default:
|
|
303
374
|
if (!isWhitespace(text)) {
|
|
@@ -312,6 +383,20 @@ class GraphmlReader {
|
|
|
312
383
|
if (!this.graphSeen) {
|
|
313
384
|
this.report.fail(GRAPHML_ISSUE.NO_GRAPH, "the document has no <graph> element");
|
|
314
385
|
}
|
|
386
|
+
// GraphML allows an edge before the nodes it joins: what waited for them is added now
|
|
387
|
+
for (const edge of this.deferred) {
|
|
388
|
+
if ("endpoints" in edge) {
|
|
389
|
+
this.expandHyperedge(edge);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
this.addEdge(edge);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
this.deferred.length = 0;
|
|
396
|
+
this.checkPorts();
|
|
397
|
+
for (const [kind, more] of this.unknownOverflow) {
|
|
398
|
+
this.report.warning("unsupported", GRAPHML_ISSUE.UNKNOWN_XML_ATTRIBUTE, `${more} more distinct attribute names on <${kind}> are not GraphML attributes and are not kept (not listed one by one)`, { element: kind });
|
|
399
|
+
}
|
|
315
400
|
const meta = { graphId: this.graphId, edgedefault: this.edgedefault, namespaces: this.namespaces };
|
|
316
401
|
this.sink.setMeta({
|
|
317
402
|
sourceFormat: FORMAT,
|
|
@@ -350,7 +435,7 @@ class GraphmlReader {
|
|
|
350
435
|
startInGraphml(name, local, attrs, line) {
|
|
351
436
|
switch (local) {
|
|
352
437
|
case "desc":
|
|
353
|
-
this.beginDesc("graph");
|
|
438
|
+
this.beginDesc("graph", line);
|
|
354
439
|
return;
|
|
355
440
|
case "key":
|
|
356
441
|
this.beginKey(attrs, line);
|
|
@@ -369,14 +454,20 @@ class GraphmlReader {
|
|
|
369
454
|
* A child of `<key>`.
|
|
370
455
|
* @param name - the element name
|
|
371
456
|
* @param local - its local name
|
|
457
|
+
* @param attrs - its attributes
|
|
372
458
|
* @param line - the line
|
|
373
459
|
*/
|
|
374
|
-
startInKey(name, local, line) {
|
|
460
|
+
startInKey(name, local, attrs, line) {
|
|
375
461
|
switch (local) {
|
|
376
462
|
case "desc":
|
|
377
|
-
this.beginDesc("key");
|
|
463
|
+
this.beginDesc("key", line);
|
|
378
464
|
return;
|
|
379
465
|
case "default":
|
|
466
|
+
this.reportUnreadAttributes("default", attrs, NO_ATTRIBUTES, line);
|
|
467
|
+
if (this.pendingKey !== null &&
|
|
468
|
+
(this.pendingKey.defaultText !== null || this.pendingKey.defaultTree !== undefined)) {
|
|
469
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.DUPLICATE_ATTRIBUTE, `key "${this.pendingKey.id ?? ""}" has a second <default>; the later one is kept`, { line, element: this.pendingKey.id });
|
|
470
|
+
}
|
|
380
471
|
this.content.key = null;
|
|
381
472
|
this.content.pendingKey = this.pendingKey;
|
|
382
473
|
this.content.text = "";
|
|
@@ -396,21 +487,25 @@ class GraphmlReader {
|
|
|
396
487
|
* @param line - the line
|
|
397
488
|
*/
|
|
398
489
|
startInGraph(name, local, attrs, line) {
|
|
490
|
+
const first = this.graphs.length === 1 && this.topGraphs === 1;
|
|
399
491
|
switch (local) {
|
|
400
492
|
case "desc":
|
|
401
|
-
if (
|
|
402
|
-
this.beginDesc("graph");
|
|
493
|
+
if (first) {
|
|
494
|
+
this.beginDesc("graph", line);
|
|
403
495
|
}
|
|
404
496
|
else {
|
|
497
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.DESC_DROPPED, `the <desc> of a ${this.graphs.length === 1 ? "second top-level" : "nested"} <graph> is not kept`, { line }, `${GRAPHML_ISSUE.DESC_DROPPED}:graph`);
|
|
405
498
|
this.ctx.push(Ctx.Skip);
|
|
406
499
|
}
|
|
407
500
|
return;
|
|
408
501
|
case "data":
|
|
409
|
-
if (
|
|
502
|
+
if (first) {
|
|
410
503
|
this.beginData(attrs, line, "graph");
|
|
411
504
|
}
|
|
412
505
|
else {
|
|
413
|
-
this.report.warnOnce("unsupported", GRAPHML_ISSUE.NESTED_GRAPH_DATA,
|
|
506
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.NESTED_GRAPH_DATA, this.graphs.length === 1
|
|
507
|
+
? "data of a second top-level <graph> cannot be kept; the graphs are merged and only the first one's attributes are kept"
|
|
508
|
+
: "data of a nested <graph> cannot be kept; only the top-level graph has attributes", { line });
|
|
414
509
|
this.ctx.push(Ctx.Skip);
|
|
415
510
|
}
|
|
416
511
|
return;
|
|
@@ -451,11 +546,14 @@ class GraphmlReader {
|
|
|
451
546
|
return;
|
|
452
547
|
case "port":
|
|
453
548
|
this.report.warnOnce("unsupported", GRAPHML_ISSUE.PORT_DECLARATION, "<port> declarations are not kept; sourceport / targetport edge attributes are", { line });
|
|
454
|
-
this.
|
|
549
|
+
this.beginPort(attrs, line);
|
|
455
550
|
return;
|
|
456
551
|
case "graph": {
|
|
457
552
|
const node = this.nodes[this.nodes.length - 1];
|
|
458
553
|
this.materializeNode(node);
|
|
554
|
+
if (node.index === INVALID_INDEX) {
|
|
555
|
+
this.report.error("missing-value", GRAPHML_ISSUE.UNKNOWN_PARENT, "the nodes of this nested <graph> lose their parent: the node holding it was skipped; they are read as top-level nodes", { line });
|
|
556
|
+
}
|
|
459
557
|
this.beginGraph(attrs, line, node.index);
|
|
460
558
|
return;
|
|
461
559
|
}
|
|
@@ -485,10 +583,84 @@ class GraphmlReader {
|
|
|
485
583
|
case "data":
|
|
486
584
|
this.beginData(attrs, line, "edge");
|
|
487
585
|
return;
|
|
586
|
+
case "graph":
|
|
587
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.EDGE_GRAPH_DROPPED, "a <graph> inside an <edge> is not supported; it is dropped with the nodes and edges it holds (counted as skipped)", { line, element: attrs.get("id") ?? null });
|
|
588
|
+
this.ctx.push(Ctx.Dropped);
|
|
589
|
+
return;
|
|
590
|
+
default:
|
|
591
|
+
this.unknownElement(name, line);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* An element inside a dropped `<graph>` (one held by an edge): counted as skipped.
|
|
596
|
+
* @param local - its local name
|
|
597
|
+
*/
|
|
598
|
+
dropStart(local) {
|
|
599
|
+
if (local === "node") {
|
|
600
|
+
this.report.counts.skippedNodes++;
|
|
601
|
+
}
|
|
602
|
+
else if (local === "edge" || local === "hyperedge") {
|
|
603
|
+
this.report.counts.skippedEdges++;
|
|
604
|
+
}
|
|
605
|
+
this.ctx.push(local === "data" || local === "desc" ? Ctx.Skip : Ctx.Dropped);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Open a `<port>`: its name is kept for the edge port check, its content is skipped.
|
|
609
|
+
* @param attrs - its attributes
|
|
610
|
+
* @param line - the line
|
|
611
|
+
*/
|
|
612
|
+
beginPort(attrs, line) {
|
|
613
|
+
this.reportUnreadAttributes("port", attrs, PORT_ATTRIBUTES, line);
|
|
614
|
+
const node = this.nodes[this.nodes.length - 1];
|
|
615
|
+
const name = attrs.get("name");
|
|
616
|
+
if (node.id !== null && name !== undefined) {
|
|
617
|
+
const id = node.restoredId ?? node.id;
|
|
618
|
+
let names = this.ports.get(id);
|
|
619
|
+
if (names === undefined) {
|
|
620
|
+
names = new Set();
|
|
621
|
+
this.ports.set(id, names);
|
|
622
|
+
}
|
|
623
|
+
names.add(name);
|
|
624
|
+
}
|
|
625
|
+
this.ctx.push(Ctx.Port);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* A child of `<port>`: a nested port declares a name too; data and desc are skipped.
|
|
629
|
+
* @param name - the element name
|
|
630
|
+
* @param local - its local name
|
|
631
|
+
* @param attrs - its attributes
|
|
632
|
+
* @param line - the line
|
|
633
|
+
*/
|
|
634
|
+
startInPort(name, local, attrs, line) {
|
|
635
|
+
switch (local) {
|
|
636
|
+
case "port":
|
|
637
|
+
this.beginPort(attrs, line);
|
|
638
|
+
return;
|
|
639
|
+
case "data":
|
|
640
|
+
case "desc":
|
|
641
|
+
this.ctx.push(Ctx.Skip);
|
|
642
|
+
return;
|
|
488
643
|
default:
|
|
489
644
|
this.unknownElement(name, line);
|
|
490
645
|
}
|
|
491
646
|
}
|
|
647
|
+
/**
|
|
648
|
+
* Report the `sourceport` / `targetport` values that name a port their node never declares
|
|
649
|
+
* (once, with the count), now that every node has been read.
|
|
650
|
+
*/
|
|
651
|
+
checkPorts() {
|
|
652
|
+
let dangling = 0;
|
|
653
|
+
let first = null;
|
|
654
|
+
for (const [node, port] of this.portRefs) {
|
|
655
|
+
if (this.ports.get(node)?.has(port) !== true) {
|
|
656
|
+
dangling++;
|
|
657
|
+
first ?? (first = `${String(node)}:${port}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (dangling > 0) {
|
|
661
|
+
this.report.warning("missing-value", GRAPHML_ISSUE.DANGLING_REFERENCE, `${dangling} edge port reference${plural(dangling)} ${agree(dangling, "names", "name")} a port their node does not declare (first: ${first ?? ""}); the values are kept`, { element: first });
|
|
662
|
+
}
|
|
663
|
+
}
|
|
492
664
|
/**
|
|
493
665
|
* A child of `<hyperedge>` (under the star / clique policies).
|
|
494
666
|
* @param name - the element name
|
|
@@ -499,6 +671,7 @@ class GraphmlReader {
|
|
|
499
671
|
startInHyperedge(name, local, attrs, line) {
|
|
500
672
|
switch (local) {
|
|
501
673
|
case "endpoint":
|
|
674
|
+
this.reportUnreadAttributes("endpoint", attrs, ENDPOINT_ATTRIBUTES, line);
|
|
502
675
|
this.readEndpoint(attrs, line);
|
|
503
676
|
this.ctx.push(Ctx.Skip);
|
|
504
677
|
return;
|
|
@@ -507,6 +680,7 @@ class GraphmlReader {
|
|
|
507
680
|
this.ctx.push(Ctx.Skip);
|
|
508
681
|
return;
|
|
509
682
|
case "desc":
|
|
683
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.DESC_DROPPED, "the <desc> of a hyperedge is not kept by the star / clique expansions", { line }, `${GRAPHML_ISSUE.DESC_DROPPED}:hyperedge`);
|
|
510
684
|
this.ctx.push(Ctx.Skip);
|
|
511
685
|
return;
|
|
512
686
|
default:
|
|
@@ -519,7 +693,7 @@ class GraphmlReader {
|
|
|
519
693
|
* @param line - the line
|
|
520
694
|
*/
|
|
521
695
|
unknownElement(name, line) {
|
|
522
|
-
this.report.warnOnce("unsupported", GRAPHML_ISSUE.UNKNOWN_ELEMENT,
|
|
696
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.UNKNOWN_ELEMENT, unknownElementMessage(name), {
|
|
523
697
|
line,
|
|
524
698
|
element: name,
|
|
525
699
|
});
|
|
@@ -528,10 +702,12 @@ class GraphmlReader {
|
|
|
528
702
|
/**
|
|
529
703
|
* Open a `<desc>`.
|
|
530
704
|
* @param target - what the text describes
|
|
705
|
+
* @param line - the line
|
|
531
706
|
*/
|
|
532
|
-
beginDesc(target) {
|
|
707
|
+
beginDesc(target, line) {
|
|
533
708
|
this.descTarget = target;
|
|
534
709
|
this.descText = "";
|
|
710
|
+
this.descLine = line;
|
|
535
711
|
this.ctx.push(Ctx.Desc);
|
|
536
712
|
}
|
|
537
713
|
/** Close a `<desc>`. */
|
|
@@ -541,6 +717,11 @@ class GraphmlReader {
|
|
|
541
717
|
this.pendingKey.desc = text;
|
|
542
718
|
}
|
|
543
719
|
else if (this.descTarget === "graph" && text.length > 0) {
|
|
720
|
+
if (this.graphDescSeen) {
|
|
721
|
+
// a <graphml> and a <graph> description: the graph has one description field
|
|
722
|
+
this.report.warning("unsupported", GRAPHML_ISSUE.DESC_DROPPED, "a second graph-level <desc> replaces the first; the earlier text is not kept", { line: this.descLine });
|
|
723
|
+
}
|
|
724
|
+
this.graphDescSeen = true;
|
|
544
725
|
this.description = text;
|
|
545
726
|
}
|
|
546
727
|
this.descTarget = null;
|
|
@@ -549,23 +730,51 @@ class GraphmlReader {
|
|
|
549
730
|
// ------------------------------------------------------------------ graphs
|
|
550
731
|
/**
|
|
551
732
|
* Report, once per element kind and attribute name, an XML attribute the importer does not read:
|
|
552
|
-
* a GraphML `parse.*` hint as ignored, anything else as
|
|
553
|
-
* `xml:` / `xsi:` attributes are not data and pass silently.
|
|
733
|
+
* a GraphML `parse.*` hint as ignored, anything else as not kept. Namespace declarations and
|
|
734
|
+
* `xml:` / `xsi:` attributes are not data and pass silently. Beyond MAX_UNKNOWN_ATTRIBUTE_NAMES
|
|
735
|
+
* distinct names per element kind the rest are counted and reported once at the end, so a file
|
|
736
|
+
* with thousands of vendor attributes does not grow the report without bound.
|
|
554
737
|
* @param kind - the element name
|
|
555
738
|
* @param attrs - the element's attributes
|
|
556
739
|
* @param known - the attributes the importer reads on that element
|
|
557
740
|
* @param line - the line
|
|
558
741
|
*/
|
|
559
742
|
reportUnreadAttributes(kind, attrs, known, line) {
|
|
743
|
+
if (attrs.size === 0) {
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
560
746
|
for (const name of attrs.keys()) {
|
|
561
747
|
if (known.has(name) || name === "xmlns" || /^(xmlns|xml|xsi):/.test(name)) {
|
|
562
748
|
continue;
|
|
563
749
|
}
|
|
564
750
|
const hint = name.startsWith("parse.");
|
|
565
751
|
const code = hint ? GRAPHML_ISSUE.PARSE_HINT_IGNORED : GRAPHML_ISSUE.UNKNOWN_XML_ATTRIBUTE;
|
|
566
|
-
this.
|
|
567
|
-
|
|
568
|
-
|
|
752
|
+
let names = this.unknownNames.get(kind);
|
|
753
|
+
if (names === undefined) {
|
|
754
|
+
names = new Set();
|
|
755
|
+
this.unknownNames.set(kind, names);
|
|
756
|
+
}
|
|
757
|
+
if (names.has(name)) {
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if (names.size >= MAX_UNKNOWN_ATTRIBUTE_NAMES && !hint) {
|
|
761
|
+
this.unknownOverflow.set(kind, (this.unknownOverflow.get(kind) ?? 0) + 1);
|
|
762
|
+
}
|
|
763
|
+
names.add(name);
|
|
764
|
+
if (names.size > MAX_UNKNOWN_ATTRIBUTE_NAMES && !hint) {
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
let message;
|
|
768
|
+
if (hint) {
|
|
769
|
+
message = `the <${kind}> parse hint ${name} is ignored`;
|
|
770
|
+
}
|
|
771
|
+
else if (SCHEMA_ATTRIBUTES.has(name)) {
|
|
772
|
+
message = `the <${kind}> attribute ${name} is not kept`;
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
message = `the <${kind}> attribute ${name} is not a GraphML attribute; it is not kept`;
|
|
776
|
+
}
|
|
777
|
+
this.report.warning("unsupported", code, message, { line, element: name });
|
|
569
778
|
}
|
|
570
779
|
}
|
|
571
780
|
/**
|
|
@@ -578,6 +787,13 @@ class GraphmlReader {
|
|
|
578
787
|
beginGraph(attrs, line, parent) {
|
|
579
788
|
this.reportUnreadAttributes("graph", attrs, GRAPH_ATTRIBUTES, line);
|
|
580
789
|
const top = this.graphs.length === 0;
|
|
790
|
+
if (top) {
|
|
791
|
+
this.topGraphs++;
|
|
792
|
+
}
|
|
793
|
+
const graphId = attrs.get("id");
|
|
794
|
+
if (graphId !== undefined && graphId.length > 0) {
|
|
795
|
+
this.graphIds.add(graphId);
|
|
796
|
+
}
|
|
581
797
|
const edgedefault = attrs.get("edgedefault");
|
|
582
798
|
let directed;
|
|
583
799
|
if (edgedefault === "directed" || edgedefault === "undirected") {
|
|
@@ -585,14 +801,24 @@ class GraphmlReader {
|
|
|
585
801
|
}
|
|
586
802
|
else if (edgedefault === undefined) {
|
|
587
803
|
directed = top ? this.options.defaultDirected : this.graphs[this.graphs.length - 1].directed;
|
|
588
|
-
|
|
804
|
+
// once per kind: a file of thousands of nested graphs without edgedefault is one finding
|
|
805
|
+
const direction = directed ? "directed" : "undirected";
|
|
806
|
+
this.report.warnOnce("validation-error", GRAPHML_ISSUE.EDGEDEFAULT_MISSING, top
|
|
807
|
+
? `<graph> has no edgedefault; read as ${direction}`
|
|
808
|
+
: `a nested <graph> has no edgedefault; it takes its container's (${direction})`, { line }, `${GRAPHML_ISSUE.EDGEDEFAULT_MISSING}:${top ? "top" : "nested"}`);
|
|
589
809
|
}
|
|
590
810
|
else {
|
|
591
811
|
directed = top ? this.options.defaultDirected : this.graphs[this.graphs.length - 1].directed;
|
|
592
812
|
this.report.error("validation-error", GRAPHML_ISSUE.INVALID_EDGEDEFAULT, `edgedefault "${edgedefault}" is neither directed nor undirected; read as ${directed ? "directed" : "undirected"}`, { line });
|
|
593
813
|
}
|
|
814
|
+
let hints = null;
|
|
594
815
|
if (top && this.graphSeen) {
|
|
595
816
|
this.report.warnOnce("unsupported", GRAPHML_ISSUE.MULTIPLE_GRAPHS, "the document holds more than one top-level <graph>; their nodes and edges are merged into one graph", { line, element: attrs.get("id") ?? null });
|
|
817
|
+
for (const name of ["parse.nodes", "parse.edges"]) {
|
|
818
|
+
if (attrs.has(name)) {
|
|
819
|
+
this.report.warnOnce("unsupported", GRAPHML_ISSUE.PARSE_HINT_IGNORED, `the ${name} hint of a second top-level <graph> is ignored`, { line, element: name }, `${GRAPHML_ISSUE.PARSE_HINT_IGNORED}:second:${name}`);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
596
822
|
}
|
|
597
823
|
else if (top) {
|
|
598
824
|
this.graphSeen = true;
|
|
@@ -601,6 +827,7 @@ class GraphmlReader {
|
|
|
601
827
|
this.direction.setHeader(directed, { line });
|
|
602
828
|
const nodes = this.hint(attrs.get("parse.nodes"), "parse.nodes", line);
|
|
603
829
|
const edges = this.hint(attrs.get("parse.edges"), "parse.edges", line);
|
|
830
|
+
hints = nodes === null && edges === null ? null : { nodes, edges };
|
|
604
831
|
if (nodes !== null || edges !== null) {
|
|
605
832
|
try {
|
|
606
833
|
this.sink.reserve(nodes ?? undefined, edges ?? undefined);
|
|
@@ -615,9 +842,24 @@ class GraphmlReader {
|
|
|
615
842
|
}
|
|
616
843
|
}
|
|
617
844
|
}
|
|
618
|
-
this.graphs.push({ directed, parent });
|
|
845
|
+
this.graphs.push({ directed, parent, hints, nodes: 0, edges: 0, line });
|
|
619
846
|
this.ctx.push(Ctx.Graph);
|
|
620
847
|
}
|
|
848
|
+
/** Close a `<graph>`: a top-level graph's count hints are checked against what it held. */
|
|
849
|
+
finishGraph() {
|
|
850
|
+
const graph = this.graphs.pop();
|
|
851
|
+
if (graph?.hints === null || graph === undefined) {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
for (const [name, hint, found] of [
|
|
855
|
+
["parse.nodes", graph.hints.nodes, graph.nodes],
|
|
856
|
+
["parse.edges", graph.hints.edges, graph.edges],
|
|
857
|
+
]) {
|
|
858
|
+
if (hint !== null && hint !== found) {
|
|
859
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.COUNT_MISMATCH, `<graph ${name}="${hint}"> but the graph holds ${found} ${name === "parse.nodes" ? "<node>" : "<edge>"} elements`, { line: graph.line, element: name });
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
621
863
|
/**
|
|
622
864
|
* A `parse.nodes` / `parse.edges` hint the sink can reserve; anything else is reported and ignored.
|
|
623
865
|
* @param text - the attribute text, or undefined
|
|
@@ -643,7 +885,12 @@ class GraphmlReader {
|
|
|
643
885
|
* @param line - the line
|
|
644
886
|
*/
|
|
645
887
|
beginKey(attrs, line) {
|
|
888
|
+
// attr.list (a list extension of some writers) and yEd's yfiles.foldertype are reported here
|
|
889
|
+
this.reportUnreadAttributes("key", attrs, KEY_ATTRIBUTES, line);
|
|
646
890
|
const id = attrs.get("id") ?? null;
|
|
891
|
+
if (id !== null && this.unknownKeyIds.delete(id)) {
|
|
892
|
+
this.report.warning("missing-value", GRAPHML_ISSUE.KEY_DECLARED_LATE, `key "${id}" is declared after data that uses it; those values were dropped (declare <key> before <graph>)`, { line, element: id });
|
|
893
|
+
}
|
|
647
894
|
const forText = attrs.get("for") ?? "all";
|
|
648
895
|
let domains;
|
|
649
896
|
switch (forText) {
|
|
@@ -712,6 +959,8 @@ class GraphmlReader {
|
|
|
712
959
|
continue;
|
|
713
960
|
}
|
|
714
961
|
if (domain === "edge" && !yfiles && isWeightField(name, this.options.weightFrom)) {
|
|
962
|
+
// networkx writes one weight key per value type (long and double): every key of
|
|
963
|
+
// that name is the weight; two of them on one edge are reported in finishData
|
|
715
964
|
weight = true;
|
|
716
965
|
this.weightOrigin ?? (this.weightOrigin = { id: key.id, title: key.attrName, type: key.attrType });
|
|
717
966
|
continue;
|
|
@@ -877,8 +1126,12 @@ class GraphmlReader {
|
|
|
877
1126
|
* @param domain - the domain of the element holding it
|
|
878
1127
|
*/
|
|
879
1128
|
beginData(attrs, line, domain) {
|
|
1129
|
+
this.reportUnreadAttributes("data", attrs, DATA_ATTRIBUTES, line);
|
|
880
1130
|
const keyId = attrs.get("key");
|
|
881
1131
|
const { content } = this;
|
|
1132
|
+
if (keyId !== undefined) {
|
|
1133
|
+
this.checkDuplicateData(keyId, domain, line);
|
|
1134
|
+
}
|
|
882
1135
|
content.key = null;
|
|
883
1136
|
content.pendingKey = null;
|
|
884
1137
|
content.domain = domain;
|
|
@@ -894,6 +1147,7 @@ class GraphmlReader {
|
|
|
894
1147
|
const entries = this.keys.get(keyId);
|
|
895
1148
|
const key = entries?.find((entry) => entry.domains.includes(domain)) ?? entries?.[0];
|
|
896
1149
|
if (key === undefined) {
|
|
1150
|
+
this.unknownKeyIds.add(keyId);
|
|
897
1151
|
this.report.error("validation-error", GRAPHML_ISSUE.UNKNOWN_KEY, `<data> references undeclared key "${keyId}"`, { line, element: keyId });
|
|
898
1152
|
}
|
|
899
1153
|
else if (!key.skipped && !key.domains.includes(domain)) {
|
|
@@ -905,6 +1159,32 @@ class GraphmlReader {
|
|
|
905
1159
|
}
|
|
906
1160
|
this.ctx.push(Ctx.Data);
|
|
907
1161
|
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Report a second `<data>` of one key on one element; the later value is kept (it overwrites).
|
|
1164
|
+
* @param keyId - the key
|
|
1165
|
+
* @param domain - the domain of the element holding it
|
|
1166
|
+
* @param line - the line
|
|
1167
|
+
*/
|
|
1168
|
+
checkDuplicateData(keyId, domain, line) {
|
|
1169
|
+
let holder = null;
|
|
1170
|
+
if (domain === "node") {
|
|
1171
|
+
holder = this.nodes.at(-1) ?? null;
|
|
1172
|
+
}
|
|
1173
|
+
else if (domain === "edge") {
|
|
1174
|
+
holder = this.edge;
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
holder = this.graphKeys;
|
|
1178
|
+
}
|
|
1179
|
+
if (holder === null) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
holder.keys ?? (holder.keys = new Set());
|
|
1183
|
+
if (holder.keys.has(keyId)) {
|
|
1184
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.DUPLICATE_ATTRIBUTE, `a second <data key="${keyId}"> on one ${domain}; the later value is kept`, { line, element: keyId });
|
|
1185
|
+
}
|
|
1186
|
+
holder.keys.add(keyId);
|
|
1187
|
+
}
|
|
908
1188
|
/**
|
|
909
1189
|
* A child element inside `<data>` / `<default>`: the content becomes a tree.
|
|
910
1190
|
* @param name - the element name
|
|
@@ -959,9 +1239,13 @@ class GraphmlReader {
|
|
|
959
1239
|
case "node": {
|
|
960
1240
|
const node = this.nodes[this.nodes.length - 1];
|
|
961
1241
|
if (key.originalId) {
|
|
962
|
-
if (typeof value
|
|
963
|
-
|
|
1242
|
+
if (typeof value !== "string" || node.index !== INVALID_INDEX) {
|
|
1243
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.ORIGINAL_ID_IGNORED, typeof value === "string"
|
|
1244
|
+
? `the ${ORIGINAL_ID_ATTRIBUTE} value comes after the node's nested <graph>, which added the node under its written id; it is not restored`
|
|
1245
|
+
: `the ${ORIGINAL_ID_ATTRIBUTE} value holds elements, not text; it is not restored`, where);
|
|
1246
|
+
return;
|
|
964
1247
|
}
|
|
1248
|
+
node.restoredId = value;
|
|
965
1249
|
return;
|
|
966
1250
|
}
|
|
967
1251
|
if (key.yfiles) {
|
|
@@ -988,8 +1272,13 @@ class GraphmlReader {
|
|
|
988
1272
|
this.report.error("validation-error", GRAPHML_ISSUE.DATA_NESTED, "a weight value must be text", where);
|
|
989
1273
|
return;
|
|
990
1274
|
}
|
|
1275
|
+
if (edge.weightKey !== null && edge.weightKey !== key.id) {
|
|
1276
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.DUPLICATE_ATTRIBUTE, `the edge has values of two weight keys ("${edge.weightKey}" and "${key.id}"); the later one is kept`, where);
|
|
1277
|
+
}
|
|
1278
|
+
edge.weightKey = key.id;
|
|
991
1279
|
try {
|
|
992
|
-
edge.weight = parseWeightText(value);
|
|
1280
|
+
edge.weight = parseWeightText(value, this.report);
|
|
1281
|
+
this.checkOverflow(value, edge.weight, key.name, where);
|
|
993
1282
|
}
|
|
994
1283
|
catch (err) {
|
|
995
1284
|
this.skipEdge(edge);
|
|
@@ -1057,7 +1346,12 @@ class GraphmlReader {
|
|
|
1057
1346
|
*/
|
|
1058
1347
|
graphics(domain, key, tree, where) {
|
|
1059
1348
|
const out = [];
|
|
1060
|
-
|
|
1349
|
+
const unmapped = [];
|
|
1350
|
+
const values = graphicsValues(domain, tree, unmapped);
|
|
1351
|
+
for (const field of unmapped) {
|
|
1352
|
+
this.report.warnOnce("validation-error", GRAPHML_ISSUE.YFILES_VALUE, `a yFiles ${domain} ${field} that is not a number is not mapped to its yfiles column (the graphics tree is kept)`, where, `${GRAPHML_ISSUE.YFILES_VALUE}:${domain}:${field}`);
|
|
1353
|
+
}
|
|
1354
|
+
for (const [field, value] of values) {
|
|
1061
1355
|
const id = `${domain}:${field}`;
|
|
1062
1356
|
let handle = this.graphicsColumns.get(id);
|
|
1063
1357
|
if (handle === undefined) {
|
|
@@ -1102,6 +1396,7 @@ class GraphmlReader {
|
|
|
1102
1396
|
if (spec.precision && losesPrecision(spec, value)) {
|
|
1103
1397
|
this.report.warnOnce("precision", PRECISION_CODE, `long values of "${target.name}" beyond 2^53 are stored as the nearest double`, { line: where.line, element: target.name });
|
|
1104
1398
|
}
|
|
1399
|
+
this.checkOverflow(value, parsed, target.name, where);
|
|
1105
1400
|
return parsed;
|
|
1106
1401
|
}
|
|
1107
1402
|
catch (err) {
|
|
@@ -1109,6 +1404,18 @@ class GraphmlReader {
|
|
|
1109
1404
|
return undefined;
|
|
1110
1405
|
}
|
|
1111
1406
|
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Report (once per column) a finite number text too large for a double, stored as Infinity.
|
|
1409
|
+
* @param text - the value text
|
|
1410
|
+
* @param value - the parsed value
|
|
1411
|
+
* @param column - the column name
|
|
1412
|
+
* @param where - the location
|
|
1413
|
+
*/
|
|
1414
|
+
checkOverflow(text, value, column, where) {
|
|
1415
|
+
if (typeof value === "number" && overflowsToInfinity(text)) {
|
|
1416
|
+
this.report.warnOnce("precision", PRECISION_CODE, `values of "${column}" beyond the double range (${text.trim()}) are stored as Infinity`, { line: where.line, element: column }, `${PRECISION_CODE}:overflow:${column}`);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1112
1419
|
// ------------------------------------------------------------------ nodes
|
|
1113
1420
|
/**
|
|
1114
1421
|
* Open a `<node>`; it is added to the sink when its data is complete (or a nested graph
|
|
@@ -1119,6 +1426,7 @@ class GraphmlReader {
|
|
|
1119
1426
|
beginNode(attrs, line) {
|
|
1120
1427
|
this.reportUnreadAttributes("node", attrs, NODE_ATTRIBUTES, line);
|
|
1121
1428
|
const graph = this.graphs[this.graphs.length - 1];
|
|
1429
|
+
graph.nodes++;
|
|
1122
1430
|
const state = {
|
|
1123
1431
|
id: null,
|
|
1124
1432
|
idText: null,
|
|
@@ -1128,6 +1436,7 @@ class GraphmlReader {
|
|
|
1128
1436
|
restoredId: null,
|
|
1129
1437
|
failed: false,
|
|
1130
1438
|
line,
|
|
1439
|
+
keys: null,
|
|
1131
1440
|
};
|
|
1132
1441
|
const idText = attrs.get("id");
|
|
1133
1442
|
if (idText === undefined || idText.length === 0) {
|
|
@@ -1167,7 +1476,10 @@ class GraphmlReader {
|
|
|
1167
1476
|
try {
|
|
1168
1477
|
const existing = this.sink.indexOf(id);
|
|
1169
1478
|
const index = this.sink.addNode(id);
|
|
1170
|
-
if (existing !== INVALID_INDEX && this.
|
|
1479
|
+
if (existing !== INVALID_INDEX && this.hubs.has(index)) {
|
|
1480
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.HUB_ID_CLASH, `node "${String(id)}" has the id of the hub a star-expanded hyperedge created earlier; the node is merged into the hub`, { line: node.line, element: String(id) });
|
|
1481
|
+
}
|
|
1482
|
+
else if (existing !== INVALID_INDEX && this.declared.has(index)) {
|
|
1171
1483
|
this.report.warning("validation-error", GRAPHML_ISSUE.DUPLICATE_NODE, `node "${String(id)}" is declared twice; the declarations are merged`, { line: node.line, element: String(id) });
|
|
1172
1484
|
}
|
|
1173
1485
|
else {
|
|
@@ -1234,10 +1546,15 @@ class GraphmlReader {
|
|
|
1234
1546
|
beginEdge(attrs, line) {
|
|
1235
1547
|
this.reportUnreadAttributes("edge", attrs, EDGE_ATTRIBUTES, line);
|
|
1236
1548
|
const graph = this.graphs[this.graphs.length - 1];
|
|
1549
|
+
graph.edges++;
|
|
1550
|
+
const idText = attrs.get("id");
|
|
1551
|
+
const sourceText = attrs.get("source");
|
|
1552
|
+
const targetText = attrs.get("target");
|
|
1237
1553
|
const edge = {
|
|
1238
1554
|
source: null,
|
|
1239
1555
|
target: null,
|
|
1240
|
-
|
|
1556
|
+
// an exporter that writes id="" for an edge without one: the same as no id
|
|
1557
|
+
id: idText === undefined || idText.length === 0 ? null : idText,
|
|
1241
1558
|
kind: graph.directed ? "directed" : "undirected",
|
|
1242
1559
|
sourcePort: attrs.get("sourceport") ?? null,
|
|
1243
1560
|
targetPort: attrs.get("targetport") ?? null,
|
|
@@ -1245,10 +1562,12 @@ class GraphmlReader {
|
|
|
1245
1562
|
pending: [],
|
|
1246
1563
|
failed: false,
|
|
1247
1564
|
line,
|
|
1565
|
+
keys: null,
|
|
1566
|
+
weightKey: null,
|
|
1567
|
+
sourceText: sourceText ?? null,
|
|
1568
|
+
targetText: targetText ?? null,
|
|
1248
1569
|
};
|
|
1249
1570
|
const where = { line, element: edge.id };
|
|
1250
|
-
const sourceText = attrs.get("source");
|
|
1251
|
-
const targetText = attrs.get("target");
|
|
1252
1571
|
if (sourceText === undefined || sourceText.length === 0) {
|
|
1253
1572
|
this.skipEdge(edge);
|
|
1254
1573
|
this.report.error("missing-value", GRAPHML_ISSUE.MISSING_ENDPOINT, "<edge> without a source", where);
|
|
@@ -1269,15 +1588,16 @@ class GraphmlReader {
|
|
|
1269
1588
|
}
|
|
1270
1589
|
const directedText = attrs.get("directed");
|
|
1271
1590
|
if (directedText !== undefined) {
|
|
1272
|
-
|
|
1591
|
+
// the schema types directed as xs:boolean: true, false, 1 or 0
|
|
1592
|
+
if (directedText === "true" || directedText === "1") {
|
|
1273
1593
|
edge.kind = "directed";
|
|
1274
1594
|
}
|
|
1275
|
-
else if (directedText === "false") {
|
|
1595
|
+
else if (directedText === "false" || directedText === "0") {
|
|
1276
1596
|
edge.kind = "undirected";
|
|
1277
1597
|
}
|
|
1278
1598
|
else {
|
|
1279
1599
|
this.skipEdge(edge);
|
|
1280
|
-
this.report.error("validation-error", GRAPHML_ISSUE.INVALID_DIRECTED, `directed="${directedText}" is neither true nor false`, where);
|
|
1600
|
+
this.report.error("validation-error", GRAPHML_ISSUE.INVALID_DIRECTED, `directed="${directedText}" is neither true nor false (nor 1 or 0)`, where);
|
|
1281
1601
|
}
|
|
1282
1602
|
}
|
|
1283
1603
|
this.edge = edge;
|
|
@@ -1296,6 +1616,28 @@ class GraphmlReader {
|
|
|
1296
1616
|
this.skipEdge(edge);
|
|
1297
1617
|
return;
|
|
1298
1618
|
}
|
|
1619
|
+
if ((!this.options.addMissingNodes &&
|
|
1620
|
+
(this.sink.indexOf(edge.source) === INVALID_INDEX ||
|
|
1621
|
+
this.sink.indexOf(edge.target) === INVALID_INDEX)) ||
|
|
1622
|
+
(edge.id !== null && this.deferredEdgeIds.has(edge.id))) {
|
|
1623
|
+
// GraphML allows nodes and edges in any order: wait for the end of the document. An
|
|
1624
|
+
// edge reusing a waiting edge's id waits behind it, so the first one keeps the id.
|
|
1625
|
+
if (edge.id !== null) {
|
|
1626
|
+
this.deferredEdgeIds.add(edge.id);
|
|
1627
|
+
}
|
|
1628
|
+
this.deferred.push(edge);
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
this.addEdge(edge);
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Push an edge through the direction resolver and write its values.
|
|
1635
|
+
* @param edge - the edge, its endpoints known
|
|
1636
|
+
*/
|
|
1637
|
+
addEdge(edge) {
|
|
1638
|
+
if (edge.source === null || edge.target === null) {
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1299
1641
|
const element = edge.id ?? `${String(edge.source)} -> ${String(edge.target)}`;
|
|
1300
1642
|
const where = { line: edge.line, element };
|
|
1301
1643
|
try {
|
|
@@ -1303,6 +1645,8 @@ class GraphmlReader {
|
|
|
1303
1645
|
this.requireNode(edge.source);
|
|
1304
1646
|
this.requireNode(edge.target);
|
|
1305
1647
|
}
|
|
1648
|
+
this.checkGraphEndpoint(edge.source, edge.sourceText, where);
|
|
1649
|
+
this.checkGraphEndpoint(edge.target, edge.targetText, where);
|
|
1306
1650
|
if (edge.id !== null && this.edgeIds.has(edge.id)) {
|
|
1307
1651
|
throw new GraphFormatError("E_DUPLICATE_EDGE_ID", `edge id "${edge.id}" is used twice`, {
|
|
1308
1652
|
id: edge.id,
|
|
@@ -1319,9 +1663,11 @@ class GraphmlReader {
|
|
|
1319
1663
|
}
|
|
1320
1664
|
if (edge.sourcePort !== null) {
|
|
1321
1665
|
this.sink.setEdgeValue(this.portColumn("source"), e, edge.sourcePort);
|
|
1666
|
+
this.portRefs.push([edge.source, edge.sourcePort]);
|
|
1322
1667
|
}
|
|
1323
1668
|
if (edge.targetPort !== null) {
|
|
1324
1669
|
this.sink.setEdgeValue(this.portColumn("target"), e, edge.targetPort);
|
|
1670
|
+
this.portRefs.push([edge.target, edge.targetPort]);
|
|
1325
1671
|
}
|
|
1326
1672
|
const { pending } = edge;
|
|
1327
1673
|
for (let i = 0; i < pending.length; i += 2) {
|
|
@@ -1343,6 +1689,18 @@ class GraphmlReader {
|
|
|
1343
1689
|
this.report.counts.skippedEdges++;
|
|
1344
1690
|
}
|
|
1345
1691
|
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Report an endpoint that names a nested `<graph>` rather than a node (a node of that id is
|
|
1694
|
+
* then created under addMissingNodes).
|
|
1695
|
+
* @param id - the endpoint id
|
|
1696
|
+
* @param text - the endpoint as written, or null
|
|
1697
|
+
* @param where - the edge's location
|
|
1698
|
+
*/
|
|
1699
|
+
checkGraphEndpoint(id, text, where) {
|
|
1700
|
+
if (text !== null && this.graphIds.has(text) && this.sink.indexOf(id) === INVALID_INDEX) {
|
|
1701
|
+
this.report.warning("validation-error", GRAPHML_ISSUE.GRAPH_ENDPOINT, `edge endpoint "${text}" names a <graph>, not a node; a node "${text}" is created`, where);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1346
1704
|
/**
|
|
1347
1705
|
* E_UNKNOWN_NODE when an endpoint was never declared (addMissingNodes false enforced by the
|
|
1348
1706
|
* importer, whatever the sink allows).
|
|
@@ -1408,6 +1766,7 @@ class GraphmlReader {
|
|
|
1408
1766
|
* @param line - the line
|
|
1409
1767
|
*/
|
|
1410
1768
|
beginHyperedge(attrs, line) {
|
|
1769
|
+
this.reportUnreadAttributes("hyperedge", attrs, HYPEREDGE_ATTRIBUTES, line);
|
|
1411
1770
|
const id = attrs.get("id") ?? null;
|
|
1412
1771
|
const where = { line, element: id };
|
|
1413
1772
|
switch (this.options.hyperedges) {
|
|
@@ -1474,13 +1833,40 @@ class GraphmlReader {
|
|
|
1474
1833
|
if (hyperedge.failed) {
|
|
1475
1834
|
return;
|
|
1476
1835
|
}
|
|
1836
|
+
if (hyperedge.endpoints.length === 0) {
|
|
1837
|
+
this.skipEdge(hyperedge);
|
|
1838
|
+
this.report.error("missing-value", GRAPHML_ISSUE.HYPEREDGE_ENDPOINT, "<hyperedge> without endpoints yields no edge", { line: hyperedge.line, element: hyperedge.id });
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
if (!this.options.addMissingNodes &&
|
|
1842
|
+
hyperedge.endpoints.some((endpoint) => this.sink.indexOf(endpoint.node) === INVALID_INDEX)) {
|
|
1843
|
+
this.deferred.push(hyperedge);
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
this.expandHyperedge(hyperedge);
|
|
1847
|
+
}
|
|
1848
|
+
/**
|
|
1849
|
+
* Expand a hyperedge to a star or a clique; under addMissingNodes false every endpoint must be
|
|
1850
|
+
* a declared node.
|
|
1851
|
+
* @param hyperedge - the hyperedge, its endpoints read
|
|
1852
|
+
*/
|
|
1853
|
+
expandHyperedge(hyperedge) {
|
|
1477
1854
|
const where = { line: hyperedge.line, element: hyperedge.id };
|
|
1478
1855
|
try {
|
|
1856
|
+
for (const endpoint of hyperedge.endpoints) {
|
|
1857
|
+
if (!this.options.addMissingNodes) {
|
|
1858
|
+
this.requireNode(endpoint.node);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
for (const node of new Set(hyperedge.endpoints.map((endpoint) => endpoint.node))) {
|
|
1862
|
+
this.countEndpoints(node, node);
|
|
1863
|
+
}
|
|
1479
1864
|
if (this.options.hyperedges === "star") {
|
|
1480
1865
|
this.expandStar(hyperedge, where);
|
|
1481
1866
|
}
|
|
1482
|
-
else {
|
|
1483
|
-
this.
|
|
1867
|
+
else if (this.expandClique(hyperedge, where) === 0) {
|
|
1868
|
+
this.skipEdge(hyperedge);
|
|
1869
|
+
this.report.error("validation-error", GRAPHML_ISSUE.HYPEREDGE_ENDPOINT, "no two endpoints of this hyperedge can be joined (all in, all out, or only one); it yields no edge", where);
|
|
1484
1870
|
}
|
|
1485
1871
|
}
|
|
1486
1872
|
catch (err) {
|
|
@@ -1503,6 +1889,7 @@ class GraphmlReader {
|
|
|
1503
1889
|
}
|
|
1504
1890
|
const hub = this.sink.addNode(hubId);
|
|
1505
1891
|
this.declared.add(hub);
|
|
1892
|
+
this.hubs.add(hub);
|
|
1506
1893
|
this.report.counts.nodes++;
|
|
1507
1894
|
if (this.hubHandle === INVALID_INDEX) {
|
|
1508
1895
|
this.hubHandle = this.sink.declareNodeColumn({
|
|
@@ -1538,9 +1925,11 @@ class GraphmlReader {
|
|
|
1538
1925
|
* joined undirected to every other endpoint; two endpoints of the same direction are not joined.
|
|
1539
1926
|
* @param hyperedge - the hyperedge
|
|
1540
1927
|
* @param where - the location for issues
|
|
1928
|
+
* @returns the number of edge elements added
|
|
1541
1929
|
*/
|
|
1542
1930
|
expandClique(hyperedge, where) {
|
|
1543
1931
|
const { endpoints } = hyperedge;
|
|
1932
|
+
let added = 0;
|
|
1544
1933
|
for (let i = 0; i < endpoints.length; i++) {
|
|
1545
1934
|
for (let j = i + 1; j < endpoints.length; j++) {
|
|
1546
1935
|
const a = endpoints[i];
|
|
@@ -1558,9 +1947,11 @@ class GraphmlReader {
|
|
|
1558
1947
|
else {
|
|
1559
1948
|
continue;
|
|
1560
1949
|
}
|
|
1950
|
+
added++;
|
|
1561
1951
|
this.report.counts.edges += this.sink.edgeCount - before;
|
|
1562
1952
|
}
|
|
1563
1953
|
}
|
|
1954
|
+
return added;
|
|
1564
1955
|
}
|
|
1565
1956
|
// ------------------------------------------------------------------ options and ids
|
|
1566
1957
|
/**
|
|
@@ -1655,12 +2046,13 @@ function resolveYfiles(options) {
|
|
|
1655
2046
|
* or when the head does not start with markup
|
|
1656
2047
|
*/
|
|
1657
2048
|
function sniffGraphml(head) {
|
|
1658
|
-
const text =
|
|
2049
|
+
const text = sniffXmlText(head.subarray(0, SNIFF_BYTES));
|
|
1659
2050
|
// Only a document that starts as markup: a JSON or CSV value may mention a `<graphml>` tag.
|
|
1660
2051
|
if (!/^\uFEFF?\s*</.test(text)) {
|
|
1661
2052
|
return 0;
|
|
1662
2053
|
}
|
|
1663
|
-
|
|
2054
|
+
// the root may carry a namespace prefix (<g:graphml xmlns:g="...">)
|
|
2055
|
+
const root = text.search(/<([\w.-]+:)?graphml[\s>/]/);
|
|
1664
2056
|
if (root >= 0) {
|
|
1665
2057
|
return text.includes(GRAPHML_NAMESPACE, root) ? 1 : 0.9;
|
|
1666
2058
|
}
|
|
@@ -1681,9 +2073,12 @@ async function importGraphml(input, sink, options) {
|
|
|
1681
2073
|
reportUnusedOptions(options, report, USED_OPTIONS);
|
|
1682
2074
|
const reader = new GraphmlReader(sink, report, common, yfilesMode);
|
|
1683
2075
|
try {
|
|
1684
|
-
await tokenizeXml(textChunks(input, report, { ...common, declaredEncoding: xmlDeclaredEncoding }), reader);
|
|
2076
|
+
await tokenizeXml(textChunks(input, report, { ...common, declaredEncoding: xmlDeclaredEncoding, xml: true }), reader);
|
|
1685
2077
|
}
|
|
1686
2078
|
catch (err) {
|
|
2079
|
+
if (err instanceof XmlEmptyInputError) {
|
|
2080
|
+
report.fail(GRAPHML_ISSUE.EMPTY_INPUT, "the input is empty (no markup at all)", { line: err.line });
|
|
2081
|
+
}
|
|
1687
2082
|
if (err instanceof XmlSyntaxError) {
|
|
1688
2083
|
report.fail(GRAPHML_ISSUE.XML_SYNTAX, err.message, { line: err.line });
|
|
1689
2084
|
}
|
|
@@ -1693,12 +2088,44 @@ async function importGraphml(input, sink, options) {
|
|
|
1693
2088
|
throwIfAborted(common.signal);
|
|
1694
2089
|
return report.finish();
|
|
1695
2090
|
}
|
|
1696
|
-
/**
|
|
2091
|
+
/**
|
|
2092
|
+
* The GraphML importer.
|
|
2093
|
+
* @category Built-in formats
|
|
2094
|
+
*/
|
|
1697
2095
|
export const graphmlImporter = Object.freeze({
|
|
1698
2096
|
format: FORMAT,
|
|
2097
|
+
options: Object.freeze(["yfiles"]),
|
|
1699
2098
|
extensions: EXTENSIONS,
|
|
1700
2099
|
mimeTypes: MIME_TYPES,
|
|
1701
2100
|
sniff: sniffGraphml,
|
|
1702
2101
|
import: importGraphml,
|
|
1703
2102
|
});
|
|
2103
|
+
/** The elements GraphML defines, for telling a misplaced one from a foreign one. */
|
|
2104
|
+
const GRAPHML_ELEMENTS = new Set([
|
|
2105
|
+
"graphml",
|
|
2106
|
+
"key",
|
|
2107
|
+
"default",
|
|
2108
|
+
"graph",
|
|
2109
|
+
"node",
|
|
2110
|
+
"edge",
|
|
2111
|
+
"hyperedge",
|
|
2112
|
+
"endpoint",
|
|
2113
|
+
"port",
|
|
2114
|
+
"data",
|
|
2115
|
+
"desc",
|
|
2116
|
+
"locator",
|
|
2117
|
+
]);
|
|
2118
|
+
/**
|
|
2119
|
+
* The message of an element skipped where it stands.
|
|
2120
|
+
* @param name - the element name
|
|
2121
|
+
* @returns a message that says where a GraphML element belongs, or that a foreign one is not GraphML
|
|
2122
|
+
*/
|
|
2123
|
+
function unknownElementMessage(name) {
|
|
2124
|
+
if (name === "key") {
|
|
2125
|
+
return "element <key> is only allowed as a child of <graphml>, before the first <graph>; it was skipped";
|
|
2126
|
+
}
|
|
2127
|
+
return GRAPHML_ELEMENTS.has(name)
|
|
2128
|
+
? `element <${name}> is not allowed at this place in a GraphML file and was skipped`
|
|
2129
|
+
: `element <${name}> is not GraphML and was skipped`;
|
|
2130
|
+
}
|
|
1704
2131
|
//# sourceMappingURL=importer.js.map
|