@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
package/dist/gexf.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { bG as TIME_TEXT_ROLE, bH as TIME_TEXT_SUFFIX, al as resolveImportOptions, a8 as ImportReportBuilder, ao as reportSinkOptions, an as reportUnusedOptions, a4 as textChunks, E as EMPTY_INPUT_CODE, X as XML_SYNTAX_CODE, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, f as STRAY_TEXT_CODE, N as NO_GRAPH_CODE, h as UNKNOWN_XML_ATTRIBUTE_CODE, l as MULTIPLE_GRAPHS_CODE, j as COUNT_MISMATCH_CODE, k as COUNT_HINT_CODE, o as DUPLICATE_ATTRIBUTE_CODE, aK as isWeightField, bI as declareAttribute, a1 as declareResolved, t as MISSING_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, ai as PARENT_CYCLE_CODE, s as MISSING_ENDPOINT_CODE, m as DUPLICATE_EDGE_ID_CODE, aL as parseWeightText, bJ as overflowsToInfinity, P as PRECISION_CODE, bK as parseDeclaredTemporal, bs as declareCompanion, bL as parseDeclaredValue, bM as losesPrecision, bN as parseTimeText, a3 as BAD_VALUE_CODE, bO as splitListText, g as UNKNOWN_ELEMENT_CODE, I as ID_MERGED_CODE, bP as timeTextCompanion, bQ as parseDecimalText, c as capabilities, L as LOSS, aE as sanitizeIds, p as pairFolding, e as explicitWeights, r as resolveExportOptions, a as checkCapabilities, bR as formatTimeValue, aa as formatF32, ab as formatF64, bS as mapDeclaredType, bT as joinListText, bU as formatTemporal, aG as formatInteger, b as plural, $ as agree, by as isCanonicalIntegerText, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, a_ as BAD_OPTIONS_CODE, B as BAD_DEFAULT_CODE, U as UNKNOWN_ATTR_TYPE_CODE, v as ENCODING_CONFLICT_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, A as COLUMN_TYPE_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE } from "./chunks/export-BTI4yQgy.js";
|
|
2
2
|
import { GraphFormatError, INVALID_INDEX, MAX_COUNT } from "@graphty/graph-format";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { c as capabilities, L as LOSS, s as sanitizeIds, a as checkCapabilities } from "./chunks/export-Bh60Dv-n.js";
|
|
6
|
-
import { j as joinText, e as encodeChunks } from "./chunks/writer-C7flM-Ih.js";
|
|
3
|
+
import { t as tokenizeXml, f as xmlDeclaredEncoding, g as XmlEmptyInputError, X as XmlSyntaxError, s as sniffXmlText, l as localName, j as isWhitespace, x as xmlIllegalTextNotes, a as escapeXmlText, e as escapeXmlAttribute } from "./chunks/escape-D0g6NNUy.js";
|
|
4
|
+
import { j as joinText, e as encodeChunks } from "./chunks/writer-DxjgHwSe.js";
|
|
7
5
|
const GEXF_FORMAT = "gexf";
|
|
8
6
|
const GEXF_NAMESPACES = {
|
|
9
7
|
"1.2": { gexf: "http://www.gexf.net/1.2draft", viz: "http://www.gexf.net/1.2draft/viz" },
|
|
@@ -287,6 +285,54 @@ const VIZ_DYNAMIC_CODE = "W_GEXF_VIZ_DYNAMIC_DROPPED";
|
|
|
287
285
|
const SPELL_OPEN_CODE = "W_GEXF_SPELL_OPEN_DROPPED";
|
|
288
286
|
const VIZ_VALUE_CODE = "W_GEXF_VIZ_VALUE";
|
|
289
287
|
const OPEN_BOUND_CONFLICT_CODE = "W_GEXF_OPEN_BOUND_CONFLICT";
|
|
288
|
+
const TIMESTAMP_CONFLICT_CODE = "W_GEXF_TIMESTAMP_CONFLICT";
|
|
289
|
+
const VALUE_OUTSIDE_OPTIONS_CODE = "W_GEXF_VALUE_OUTSIDE_OPTIONS";
|
|
290
|
+
const VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.1", "1.2", "1.3"]);
|
|
291
|
+
function namespaceVersion(ns) {
|
|
292
|
+
const match = ns === null ? null : /gexf\.net\/(1\.[0-3])/.exec(ns);
|
|
293
|
+
return match === null ? null : match[1];
|
|
294
|
+
}
|
|
295
|
+
function isVizNamespace(ns) {
|
|
296
|
+
return ns !== null && /(gexf\.net\/.*viz|gephi\.org\/gexf\/viz)\/?$/.test(ns);
|
|
297
|
+
}
|
|
298
|
+
const MAX_UNKNOWN_ATTRIBUTE_NAMES = 16;
|
|
299
|
+
const ELEMENT_ATTRIBUTES = {
|
|
300
|
+
gexf: /* @__PURE__ */ new Set(["version", "variant"]),
|
|
301
|
+
meta: /* @__PURE__ */ new Set(["lastmodifieddate"]),
|
|
302
|
+
graph: /* @__PURE__ */ new Set([
|
|
303
|
+
"defaultedgetype",
|
|
304
|
+
"mode",
|
|
305
|
+
"type",
|
|
306
|
+
"timeformat",
|
|
307
|
+
"timerepresentation",
|
|
308
|
+
"idtype",
|
|
309
|
+
"start",
|
|
310
|
+
"end",
|
|
311
|
+
"timestamp",
|
|
312
|
+
"startopen",
|
|
313
|
+
"endopen"
|
|
314
|
+
]),
|
|
315
|
+
// `type` is GEXF 1.0's name for `mode` (static | dynamic)
|
|
316
|
+
attributes: /* @__PURE__ */ new Set(["class", "mode", "type", "start", "end", "startopen", "endopen"]),
|
|
317
|
+
attribute: /* @__PURE__ */ new Set(["id", "title", "type"]),
|
|
318
|
+
attvalue: /* @__PURE__ */ new Set(["for", "value", "start", "end", "timestamp", "startopen", "endopen", "id"]),
|
|
319
|
+
spell: /* @__PURE__ */ new Set(["start", "end", "timestamp", "startopen", "endopen"]),
|
|
320
|
+
parent: /* @__PURE__ */ new Set(["for"]),
|
|
321
|
+
nodes: /* @__PURE__ */ new Set(["count"]),
|
|
322
|
+
edges: /* @__PURE__ */ new Set(["count"])
|
|
323
|
+
};
|
|
324
|
+
const COUNT_TEXT = /^\d+$/;
|
|
325
|
+
const DATE_TEXT = /^-?\d{4,}-\d{2}-\d{2}(.*)$/s;
|
|
326
|
+
const TIME_TEXT = /^T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?/;
|
|
327
|
+
const ZONE_TEXT = /^(?:Z|[+-]\d{2}:\d{2})?$/;
|
|
328
|
+
function isDateText(text) {
|
|
329
|
+
const m = DATE_TEXT.exec(text);
|
|
330
|
+
if (m === null) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
const time = TIME_TEXT.exec(m[1])?.[0] ?? "";
|
|
334
|
+
return ZONE_TEXT.test(m[1].slice(time.length));
|
|
335
|
+
}
|
|
290
336
|
const EDGE_TYPES = /* @__PURE__ */ new Set(["directed", "undirected", "mutual"]);
|
|
291
337
|
function edgeTypeKeyword(text) {
|
|
292
338
|
return text.trim().toLowerCase();
|
|
@@ -448,8 +494,13 @@ class GexfReader {
|
|
|
448
494
|
this.edgeFrame = {
|
|
449
495
|
index: INVALID_INDEX,
|
|
450
496
|
mirror: INVALID_INDEX,
|
|
451
|
-
where: { line: 0, element: null }
|
|
497
|
+
where: { line: 0, element: null },
|
|
498
|
+
xmlWeight: null
|
|
452
499
|
};
|
|
500
|
+
this.attvalueIds = /* @__PURE__ */ new Set();
|
|
501
|
+
this.sections = [];
|
|
502
|
+
this.unknownNames = /* @__PURE__ */ new Map();
|
|
503
|
+
this.unknownOverflow = /* @__PURE__ */ new Map();
|
|
453
504
|
this.valueWhere = { line: 0, element: null };
|
|
454
505
|
this.attributeGroup = null;
|
|
455
506
|
this.pendingAttribute = null;
|
|
@@ -494,15 +545,20 @@ class GexfReader {
|
|
|
494
545
|
};
|
|
495
546
|
}
|
|
496
547
|
// ---------------------------------------------------------------- events
|
|
497
|
-
start(name, attrs, line) {
|
|
548
|
+
start(name, attrs, line, ns = "") {
|
|
498
549
|
const parent = this.ctx.length === 0 ? null : this.ctx[this.ctx.length - 1];
|
|
499
550
|
const local = localName(name);
|
|
551
|
+
if (ns === null && parent !== null && parent !== 14 && parent !== 2 && parent !== 6 && !name.startsWith("viz:")) {
|
|
552
|
+
this.unknownElement(name, line);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
500
555
|
switch (parent) {
|
|
501
556
|
case null:
|
|
502
557
|
if (local !== "gexf") {
|
|
503
558
|
this.report.fail(NOT_GEXF_CODE, `the root element is <${name}>, not <gexf>`, { line });
|
|
504
559
|
}
|
|
505
|
-
this.
|
|
560
|
+
this.checkAttributes("gexf", attrs, line);
|
|
561
|
+
this.readRoot(attrs, ns, line);
|
|
506
562
|
this.ctx.push(
|
|
507
563
|
0
|
|
508
564
|
/* Gexf */
|
|
@@ -527,7 +583,7 @@ class GexfReader {
|
|
|
527
583
|
this.startInNodes(name, local, attrs, line);
|
|
528
584
|
return;
|
|
529
585
|
case 8:
|
|
530
|
-
this.startInNode(name, local, attrs, line);
|
|
586
|
+
this.startInNode(name, local, attrs, line, ns);
|
|
531
587
|
return;
|
|
532
588
|
case 9:
|
|
533
589
|
this.startInAttvalues(name, local, attrs, line);
|
|
@@ -542,7 +598,7 @@ class GexfReader {
|
|
|
542
598
|
this.startInEdges(name, local, attrs, line);
|
|
543
599
|
return;
|
|
544
600
|
case 13:
|
|
545
|
-
this.startInEdge(name, local, attrs, line);
|
|
601
|
+
this.startInEdge(name, local, attrs, line, ns);
|
|
546
602
|
return;
|
|
547
603
|
case 2:
|
|
548
604
|
case 6:
|
|
@@ -585,6 +641,10 @@ class GexfReader {
|
|
|
585
641
|
case 8:
|
|
586
642
|
this.nodeStack.pop();
|
|
587
643
|
return;
|
|
644
|
+
case 7:
|
|
645
|
+
case 12:
|
|
646
|
+
this.finishSection();
|
|
647
|
+
return;
|
|
588
648
|
case 13:
|
|
589
649
|
this.edge = null;
|
|
590
650
|
return;
|
|
@@ -595,8 +655,6 @@ class GexfReader {
|
|
|
595
655
|
this.finishSpells();
|
|
596
656
|
return;
|
|
597
657
|
case 0:
|
|
598
|
-
case 7:
|
|
599
|
-
case 12:
|
|
600
658
|
case 9:
|
|
601
659
|
case 14:
|
|
602
660
|
case void 0:
|
|
@@ -642,16 +700,40 @@ class GexfReader {
|
|
|
642
700
|
if (!this.graphSeen) {
|
|
643
701
|
this.report.fail(NO_GRAPH_CODE, "the document has no <graph> element");
|
|
644
702
|
}
|
|
703
|
+
for (const [kind, more] of this.unknownOverflow) {
|
|
704
|
+
this.report.warning(
|
|
705
|
+
"unsupported",
|
|
706
|
+
UNKNOWN_XML_ATTRIBUTE_CODE,
|
|
707
|
+
`${more} more distinct attribute names on <${kind}> are not GEXF attributes and are not kept (not listed one by one)`,
|
|
708
|
+
{ element: kind }
|
|
709
|
+
);
|
|
710
|
+
}
|
|
645
711
|
}
|
|
646
712
|
// ---------------------------------------------------------------- root, meta, graph
|
|
647
713
|
/**
|
|
648
|
-
* Record the root's version
|
|
714
|
+
* Record the root's version: as written when known; the namespace's when absent; an unknown
|
|
715
|
+
* one is kept as written and reported.
|
|
649
716
|
* @param attrs - the `<gexf>` attributes
|
|
717
|
+
* @param ns - the root's namespace
|
|
718
|
+
* @param line - the line
|
|
650
719
|
*/
|
|
651
|
-
readRoot(attrs) {
|
|
720
|
+
readRoot(attrs, ns, line) {
|
|
652
721
|
const version = attrs.get("version");
|
|
653
722
|
if (version !== void 0 && version.length > 0) {
|
|
654
723
|
this.meta.sourceVersion = version;
|
|
724
|
+
if (!VERSIONS.has(version)) {
|
|
725
|
+
this.report.warning(
|
|
726
|
+
"validation-error",
|
|
727
|
+
HEADER_VALUE_CODE,
|
|
728
|
+
`<gexf version="${version}"> is not a GEXF version graph-io knows (1.0 to 1.3); read as GEXF 1.3`,
|
|
729
|
+
{ line, element: "version" }
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
const implied = namespaceVersion(ns);
|
|
735
|
+
if (implied !== null) {
|
|
736
|
+
this.meta.sourceVersion = implied;
|
|
655
737
|
}
|
|
656
738
|
}
|
|
657
739
|
/**
|
|
@@ -664,9 +746,18 @@ class GexfReader {
|
|
|
664
746
|
startInGexf(name, local, attrs, line) {
|
|
665
747
|
switch (local) {
|
|
666
748
|
case "meta": {
|
|
749
|
+
this.checkAttributes("meta", attrs, line);
|
|
667
750
|
const modified = attrs.get("lastmodifieddate");
|
|
668
751
|
if (modified !== void 0 && modified.length > 0) {
|
|
669
752
|
this.meta.modified = modified;
|
|
753
|
+
if (!isDateText(modified.trim())) {
|
|
754
|
+
this.report.warning(
|
|
755
|
+
"validation-error",
|
|
756
|
+
HEADER_VALUE_CODE,
|
|
757
|
+
`<meta lastmodifieddate="${modified}"> is not an xs:date; kept as written`,
|
|
758
|
+
{ line, element: "lastmodifieddate" }
|
|
759
|
+
);
|
|
760
|
+
}
|
|
670
761
|
}
|
|
671
762
|
this.ctx.push(
|
|
672
763
|
1
|
|
@@ -675,13 +766,18 @@ class GexfReader {
|
|
|
675
766
|
return;
|
|
676
767
|
}
|
|
677
768
|
case "graph":
|
|
769
|
+
this.checkAttributes("graph", attrs, line);
|
|
678
770
|
if (this.graphSeen) {
|
|
679
|
-
this.report.
|
|
680
|
-
|
|
681
|
-
|
|
771
|
+
this.report.warnOnce(
|
|
772
|
+
"unsupported",
|
|
773
|
+
MULTIPLE_GRAPHS_CODE,
|
|
774
|
+
"a second <graph> element; its nodes and edges are merged into the first and its header is ignored",
|
|
775
|
+
{ line }
|
|
776
|
+
);
|
|
777
|
+
} else {
|
|
778
|
+
this.graphSeen = true;
|
|
779
|
+
this.readHeader(attrs, line);
|
|
682
780
|
}
|
|
683
|
-
this.graphSeen = true;
|
|
684
|
-
this.readHeader(attrs, line);
|
|
685
781
|
this.ctx.push(
|
|
686
782
|
3
|
|
687
783
|
/* Graph */
|
|
@@ -726,8 +822,11 @@ class GexfReader {
|
|
|
726
822
|
this.metaField = null;
|
|
727
823
|
this.metaText = "";
|
|
728
824
|
}
|
|
729
|
-
/** Close `<meta>`:
|
|
825
|
+
/** Close `<meta>`: the patch is applied with the graph header, or now when `<meta>` follows the graph. */
|
|
730
826
|
finishMeta() {
|
|
827
|
+
if (this.graphSeen) {
|
|
828
|
+
this.sink.setMeta(this.meta);
|
|
829
|
+
}
|
|
731
830
|
}
|
|
732
831
|
/**
|
|
733
832
|
* Read `<graph defaultedgetype mode timeformat timerepresentation idtype start end timestamp>`
|
|
@@ -824,11 +923,7 @@ class GexfReader {
|
|
|
824
923
|
return;
|
|
825
924
|
case "nodes":
|
|
826
925
|
this.nodesSeen = true;
|
|
827
|
-
this.
|
|
828
|
-
this.ctx.push(
|
|
829
|
-
7
|
|
830
|
-
/* Nodes */
|
|
831
|
-
);
|
|
926
|
+
this.beginSection(attrs, "node", line);
|
|
832
927
|
return;
|
|
833
928
|
case "edges":
|
|
834
929
|
if (!this.nodesSeen) {
|
|
@@ -840,39 +935,64 @@ class GexfReader {
|
|
|
840
935
|
);
|
|
841
936
|
}
|
|
842
937
|
this.resolveParents();
|
|
843
|
-
this.
|
|
844
|
-
this.ctx.push(
|
|
845
|
-
12
|
|
846
|
-
/* Edges */
|
|
847
|
-
);
|
|
938
|
+
this.beginSection(attrs, "edge", line);
|
|
848
939
|
return;
|
|
849
940
|
default:
|
|
850
941
|
this.unknownElement(name, line);
|
|
851
942
|
}
|
|
852
943
|
}
|
|
944
|
+
/**
|
|
945
|
+
* Open a `<nodes>` / `<edges>` section: its count hint is reserved and later compared with the
|
|
946
|
+
* elements the section holds.
|
|
947
|
+
* @param attrs - the section's attributes
|
|
948
|
+
* @param domain - node or edge
|
|
949
|
+
* @param line - the line
|
|
950
|
+
*/
|
|
951
|
+
beginSection(attrs, domain, line) {
|
|
952
|
+
this.checkAttributes(`${domain}s`, attrs, line);
|
|
953
|
+
this.sections.push({ domain, hint: this.reserve(attrs, domain, line), seen: 0, line });
|
|
954
|
+
this.ctx.push(
|
|
955
|
+
domain === "node" ? 7 : 12
|
|
956
|
+
/* Edges */
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
/** Close a `<nodes>` / `<edges>` section: a count hint that disagrees is reported. */
|
|
960
|
+
finishSection() {
|
|
961
|
+
const section = this.sections.pop();
|
|
962
|
+
if (section?.hint === void 0 || section.hint === null || section.hint === section.seen) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
this.report.warning(
|
|
966
|
+
"validation-error",
|
|
967
|
+
COUNT_MISMATCH_CODE,
|
|
968
|
+
`<${section.domain}s count="${section.hint}"> but the section holds ${section.seen} <${section.domain}> elements (nested ones included)`,
|
|
969
|
+
{ line: section.line, element: "count" }
|
|
970
|
+
);
|
|
971
|
+
}
|
|
853
972
|
/**
|
|
854
973
|
* Pass a section's `count` hint to the sink; a hint the sink cannot reserve is a warning.
|
|
855
974
|
* @param attrs - the `<nodes>` or `<edges>` attributes
|
|
856
975
|
* @param domain - which count it is
|
|
857
976
|
* @param line - the line
|
|
977
|
+
* @returns the hint, or null when absent or ignored
|
|
858
978
|
*/
|
|
859
979
|
reserve(attrs, domain, line) {
|
|
860
980
|
const text = attrs.get("count");
|
|
861
981
|
if (text === void 0) {
|
|
862
|
-
return;
|
|
982
|
+
return null;
|
|
863
983
|
}
|
|
864
|
-
const count = Number(text);
|
|
865
|
-
if (!Number.
|
|
984
|
+
const count = COUNT_TEXT.test(text) ? Number(text) : Number.NaN;
|
|
985
|
+
if (!Number.isSafeInteger(count) || count > MAX_COUNT) {
|
|
866
986
|
this.report.warning(
|
|
867
987
|
"validation-error",
|
|
868
988
|
COUNT_HINT_CODE,
|
|
869
989
|
`<${domain}s count="${text}"> is not a count the sink can reserve; ignored`,
|
|
870
990
|
{ line, element: "count" }
|
|
871
991
|
);
|
|
872
|
-
return;
|
|
992
|
+
return null;
|
|
873
993
|
}
|
|
874
994
|
if (count === 0) {
|
|
875
|
-
return;
|
|
995
|
+
return count;
|
|
876
996
|
}
|
|
877
997
|
try {
|
|
878
998
|
if (domain === "node") {
|
|
@@ -889,6 +1009,7 @@ class GexfReader {
|
|
|
889
1009
|
element: "count"
|
|
890
1010
|
});
|
|
891
1011
|
}
|
|
1012
|
+
return count;
|
|
892
1013
|
}
|
|
893
1014
|
// ---------------------------------------------------------------- attribute declarations
|
|
894
1015
|
/**
|
|
@@ -897,6 +1018,7 @@ class GexfReader {
|
|
|
897
1018
|
* @param line - the line
|
|
898
1019
|
*/
|
|
899
1020
|
beginAttributes(attrs, line) {
|
|
1021
|
+
this.checkAttributes("attributes", attrs, line);
|
|
900
1022
|
const cls = attrs.get("class");
|
|
901
1023
|
const where = { line };
|
|
902
1024
|
let domain = null;
|
|
@@ -910,7 +1032,7 @@ class GexfReader {
|
|
|
910
1032
|
where
|
|
911
1033
|
);
|
|
912
1034
|
}
|
|
913
|
-
const mode = attrs.get("mode");
|
|
1035
|
+
const mode = attrs.get("mode") ?? attrs.get("type");
|
|
914
1036
|
if (mode !== void 0 && mode !== "static" && mode !== "dynamic") {
|
|
915
1037
|
this.warnHeader("mode", mode, where);
|
|
916
1038
|
}
|
|
@@ -932,6 +1054,7 @@ class GexfReader {
|
|
|
932
1054
|
this.unknownElement(name, line);
|
|
933
1055
|
return;
|
|
934
1056
|
}
|
|
1057
|
+
this.checkAttributes("attribute", attrs, line);
|
|
935
1058
|
const group = this.attributeGroup;
|
|
936
1059
|
if (group === null || group.domain === null) {
|
|
937
1060
|
this.ctx.push(
|
|
@@ -1022,6 +1145,14 @@ class GexfReader {
|
|
|
1022
1145
|
);
|
|
1023
1146
|
return;
|
|
1024
1147
|
}
|
|
1148
|
+
if (this.unknownAttributes.has(`${domain}:${id}`)) {
|
|
1149
|
+
report.warning(
|
|
1150
|
+
"missing-value",
|
|
1151
|
+
UNKNOWN_ATTRIBUTE_CODE,
|
|
1152
|
+
`${domain} attribute "${id}" is declared after values that use it; those values were dropped (declare <attributes> before <nodes>)`,
|
|
1153
|
+
where
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1025
1156
|
const title = attrs.get("title") ?? null;
|
|
1026
1157
|
const type = attrs.get("type") ?? null;
|
|
1027
1158
|
if (type === null) {
|
|
@@ -1033,7 +1164,14 @@ class GexfReader {
|
|
|
1033
1164
|
);
|
|
1034
1165
|
}
|
|
1035
1166
|
const name = title !== null && title.length > 0 ? title : id;
|
|
1036
|
-
if (domain === "edge" && isWeightField(name, options.weightFrom)) {
|
|
1167
|
+
if (domain === "edge" && this.weightAttr !== null && isWeightField(name, options.weightFrom)) {
|
|
1168
|
+
report.warning(
|
|
1169
|
+
"validation-error",
|
|
1170
|
+
DUPLICATE_ATTRIBUTE_CODE,
|
|
1171
|
+
`edge attribute "${id}" is also titled ${name}; attribute "${this.weightAttr.id}" is the weight, "${id}" is kept as a column`,
|
|
1172
|
+
where
|
|
1173
|
+
);
|
|
1174
|
+
} else if (domain === "edge" && isWeightField(name, options.weightFrom)) {
|
|
1037
1175
|
const declared2 = declareAttribute({ format: GEXF_FORMAT, id, title, type, long: options.long });
|
|
1038
1176
|
for (const issue of declared2.issues) {
|
|
1039
1177
|
report.warning(issue.category, issue.code, issue.message, where);
|
|
@@ -1044,7 +1182,8 @@ class GexfReader {
|
|
|
1044
1182
|
}
|
|
1045
1183
|
const declaredNames = domain === "node" ? this.declaredNodeNames : this.declaredEdgeNames;
|
|
1046
1184
|
const reserved = domain === "node" ? RESERVED_NODE_NAMES : RESERVED_EDGE_NAMES;
|
|
1047
|
-
const
|
|
1185
|
+
const weightName = domain === "edge" && this.weightAttr !== null ? options.weightFrom : null;
|
|
1186
|
+
const taken = (candidate) => reserved.has(candidate) || declaredNames.has(candidate) || candidate === weightName;
|
|
1048
1187
|
const input = {
|
|
1049
1188
|
format: GEXF_FORMAT,
|
|
1050
1189
|
id,
|
|
@@ -1117,6 +1256,7 @@ class GexfReader {
|
|
|
1117
1256
|
const enclosing = this.nodeStack.length === 0 ? INVALID_INDEX : this.nodeStack[this.nodeStack.length - 1].index;
|
|
1118
1257
|
const idText = attrs.get("id");
|
|
1119
1258
|
const where = { line, element: idText ?? attrs.get("label") ?? null };
|
|
1259
|
+
this.countInSection("node");
|
|
1120
1260
|
this.checkAttributeNames(attrs, NODE_ATTRIBUTES, "node", where);
|
|
1121
1261
|
if (idText === void 0) {
|
|
1122
1262
|
report.error("missing-value", MISSING_ID_CODE, "<node> without an id", where);
|
|
@@ -1128,6 +1268,15 @@ class GexfReader {
|
|
|
1128
1268
|
);
|
|
1129
1269
|
return;
|
|
1130
1270
|
}
|
|
1271
|
+
if (this.meta.idType === "integer" && !/^\s*[+-]?\d+\s*$/.test(idText)) {
|
|
1272
|
+
report.warnOnce(
|
|
1273
|
+
"validation-error",
|
|
1274
|
+
HEADER_VALUE_CODE,
|
|
1275
|
+
`node id "${idText}" is not an integer although the graph declares idtype="integer"; ids follow the ids option`,
|
|
1276
|
+
where,
|
|
1277
|
+
`${HEADER_VALUE_CODE}:idtype`
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1131
1280
|
let index;
|
|
1132
1281
|
try {
|
|
1133
1282
|
const id = this.coerceId(idText, where);
|
|
@@ -1164,6 +1313,10 @@ class GexfReader {
|
|
|
1164
1313
|
if (label !== void 0) {
|
|
1165
1314
|
this.nodeColumns.label.set(sink, report, index, label, where);
|
|
1166
1315
|
}
|
|
1316
|
+
} catch (err) {
|
|
1317
|
+
report.recordError(err, where);
|
|
1318
|
+
}
|
|
1319
|
+
try {
|
|
1167
1320
|
const pid = attrs.get("pid");
|
|
1168
1321
|
if (pid !== void 0) {
|
|
1169
1322
|
this.parentRefs.push({
|
|
@@ -1175,19 +1328,36 @@ class GexfReader {
|
|
|
1175
1328
|
} else if (enclosing !== INVALID_INDEX) {
|
|
1176
1329
|
this.parentRefs.push({ child: index, parentId: null, parentIndex: enclosing, where });
|
|
1177
1330
|
}
|
|
1331
|
+
} catch (err) {
|
|
1332
|
+
report.recordError(err, where);
|
|
1333
|
+
}
|
|
1334
|
+
try {
|
|
1178
1335
|
this.writeLifetime(attrs, index, this.nodeColumns, where);
|
|
1179
1336
|
} catch (err) {
|
|
1180
1337
|
report.recordError(err, where);
|
|
1181
1338
|
}
|
|
1182
1339
|
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Count a `<node>` / `<edge>` element in the open sections of its kind, for the count hint
|
|
1342
|
+
* check: a `<nodes count>` counts the nodes nested in its nodes too.
|
|
1343
|
+
* @param domain - node or edge
|
|
1344
|
+
*/
|
|
1345
|
+
countInSection(domain) {
|
|
1346
|
+
for (const section of this.sections) {
|
|
1347
|
+
if (section.domain === domain) {
|
|
1348
|
+
section.seen++;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1183
1352
|
/**
|
|
1184
1353
|
* A child of `<node>`.
|
|
1185
1354
|
* @param name - the element name
|
|
1186
1355
|
* @param local - its local name
|
|
1187
1356
|
* @param attrs - its attributes
|
|
1188
1357
|
* @param line - the line
|
|
1358
|
+
* @param ns - the element's namespace
|
|
1189
1359
|
*/
|
|
1190
|
-
startInNode(name, local, attrs, line) {
|
|
1360
|
+
startInNode(name, local, attrs, line, ns) {
|
|
1191
1361
|
const frame = this.nodeStack[this.nodeStack.length - 1];
|
|
1192
1362
|
if (frame.index === INVALID_INDEX && local !== "nodes") {
|
|
1193
1363
|
this.ctx.push(
|
|
@@ -1196,8 +1366,17 @@ class GexfReader {
|
|
|
1196
1366
|
);
|
|
1197
1367
|
return;
|
|
1198
1368
|
}
|
|
1369
|
+
if (frame.index === INVALID_INDEX) {
|
|
1370
|
+
this.report.error(
|
|
1371
|
+
"missing-value",
|
|
1372
|
+
UNKNOWN_PARENT_CODE,
|
|
1373
|
+
"the nodes nested in this skipped <node> lose their parent; they are read as top-level nodes",
|
|
1374
|
+
{ line }
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1199
1377
|
switch (local) {
|
|
1200
1378
|
case "attvalues":
|
|
1379
|
+
this.attvalueIds.clear();
|
|
1201
1380
|
this.ctx.push(
|
|
1202
1381
|
9
|
|
1203
1382
|
/* Attvalues */
|
|
@@ -1220,16 +1399,16 @@ class GexfReader {
|
|
|
1220
1399
|
);
|
|
1221
1400
|
return;
|
|
1222
1401
|
case "nodes":
|
|
1223
|
-
this.
|
|
1224
|
-
this.ctx.push(
|
|
1225
|
-
7
|
|
1226
|
-
/* Nodes */
|
|
1227
|
-
);
|
|
1402
|
+
this.beginSection(attrs, "node", line);
|
|
1228
1403
|
return;
|
|
1229
1404
|
case "color":
|
|
1230
1405
|
case "position":
|
|
1231
1406
|
case "size":
|
|
1232
1407
|
case "shape":
|
|
1408
|
+
if (!isViz(name, ns)) {
|
|
1409
|
+
this.unknownElement(name, line);
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1233
1412
|
this.writeViz(name, local, attrs, "node", frame.index, frame.where);
|
|
1234
1413
|
this.ctx.push(
|
|
1235
1414
|
14
|
|
@@ -1256,10 +1435,16 @@ class GexfReader {
|
|
|
1256
1435
|
14
|
|
1257
1436
|
/* Skip */
|
|
1258
1437
|
);
|
|
1438
|
+
this.checkAttributes("parent", attrs, line);
|
|
1259
1439
|
const frame = this.nodeStack[this.nodeStack.length - 1];
|
|
1260
1440
|
const text = attrs.get("for");
|
|
1261
1441
|
if (text === void 0) {
|
|
1262
|
-
this.report.
|
|
1442
|
+
this.report.error(
|
|
1443
|
+
"missing-value",
|
|
1444
|
+
UNKNOWN_PARENT_CODE,
|
|
1445
|
+
"<parent> without a for attribute names no parent",
|
|
1446
|
+
frame.where
|
|
1447
|
+
);
|
|
1263
1448
|
return;
|
|
1264
1449
|
}
|
|
1265
1450
|
try {
|
|
@@ -1286,6 +1471,15 @@ class GexfReader {
|
|
|
1286
1471
|
const lists = this.parentsRefs;
|
|
1287
1472
|
this.parentRefs = [];
|
|
1288
1473
|
this.parentsRefs = [];
|
|
1474
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
1475
|
+
const isAncestorOrSelf = (candidate, of) => {
|
|
1476
|
+
for (let at = of; at !== void 0; at = parentOf.get(at)) {
|
|
1477
|
+
if (at === candidate) {
|
|
1478
|
+
return true;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
return false;
|
|
1482
|
+
};
|
|
1289
1483
|
for (const ref of refs) {
|
|
1290
1484
|
let parent = ref.parentIndex;
|
|
1291
1485
|
if (ref.parentId !== null) {
|
|
@@ -1300,8 +1494,21 @@ class GexfReader {
|
|
|
1300
1494
|
continue;
|
|
1301
1495
|
}
|
|
1302
1496
|
}
|
|
1497
|
+
if (parentOf.get(ref.child) === parent) {
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
if (isAncestorOrSelf(ref.child, parent)) {
|
|
1501
|
+
report.error(
|
|
1502
|
+
"validation-error",
|
|
1503
|
+
PARENT_CYCLE_CODE,
|
|
1504
|
+
`the parent link of node "${ref.where.element ?? "?"}" would close a parent cycle; it is dropped`,
|
|
1505
|
+
ref.where
|
|
1506
|
+
);
|
|
1507
|
+
continue;
|
|
1508
|
+
}
|
|
1303
1509
|
try {
|
|
1304
1510
|
this.parentColumn.set(sink, report, ref.child, parent, ref.where);
|
|
1511
|
+
parentOf.set(ref.child, parent);
|
|
1305
1512
|
} catch (err) {
|
|
1306
1513
|
report.recordError(err, ref.where);
|
|
1307
1514
|
}
|
|
@@ -1362,6 +1569,7 @@ class GexfReader {
|
|
|
1362
1569
|
const { where } = this.edgeFrame;
|
|
1363
1570
|
where.line = line;
|
|
1364
1571
|
where.element = idText ?? edgeElement(sourceText, targetText);
|
|
1572
|
+
this.countInSection("edge");
|
|
1365
1573
|
this.checkAttributeNames(attrs, EDGE_ATTRIBUTES, "edge", where);
|
|
1366
1574
|
if (sourceText === void 0 || targetText === void 0) {
|
|
1367
1575
|
report.error(
|
|
@@ -1389,18 +1597,15 @@ class GexfReader {
|
|
|
1389
1597
|
}
|
|
1390
1598
|
kind = type;
|
|
1391
1599
|
}
|
|
1392
|
-
if (idText !== void 0) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
return;
|
|
1402
|
-
}
|
|
1403
|
-
this.edgeIds.add(idText);
|
|
1600
|
+
if (idText !== void 0 && this.edgeIds.has(idText)) {
|
|
1601
|
+
report.error(
|
|
1602
|
+
"validation-error",
|
|
1603
|
+
DUPLICATE_EDGE_ID_CODE,
|
|
1604
|
+
`edge id "${idText}" is declared more than once; the edge is skipped`,
|
|
1605
|
+
where
|
|
1606
|
+
);
|
|
1607
|
+
report.counts.skippedEdges++;
|
|
1608
|
+
return;
|
|
1404
1609
|
}
|
|
1405
1610
|
let index;
|
|
1406
1611
|
try {
|
|
@@ -1427,9 +1632,13 @@ class GexfReader {
|
|
|
1427
1632
|
report.counts.skippedEdges++;
|
|
1428
1633
|
return;
|
|
1429
1634
|
}
|
|
1635
|
+
if (idText !== void 0) {
|
|
1636
|
+
this.edgeIds.add(idText);
|
|
1637
|
+
}
|
|
1430
1638
|
const frame = this.edgeFrame;
|
|
1431
1639
|
frame.index = index;
|
|
1432
1640
|
frame.mirror = this.resolver.lastMirror;
|
|
1641
|
+
frame.xmlWeight = attrs.get("weight") ?? null;
|
|
1433
1642
|
this.edge = frame;
|
|
1434
1643
|
try {
|
|
1435
1644
|
if (idText !== void 0) {
|
|
@@ -1469,7 +1678,26 @@ class GexfReader {
|
|
|
1469
1678
|
);
|
|
1470
1679
|
return void 0;
|
|
1471
1680
|
}
|
|
1472
|
-
|
|
1681
|
+
const weight = parseWeightText(text, this.report);
|
|
1682
|
+
this.checkOverflow(text, where);
|
|
1683
|
+
return weight;
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Report (once) a weight text too large for a double, stored as Infinity; `INF` itself is a
|
|
1687
|
+
* legal weight (design section 3.7) and is not reported.
|
|
1688
|
+
* @param text - the weight text
|
|
1689
|
+
* @param where - the location
|
|
1690
|
+
*/
|
|
1691
|
+
checkOverflow(text, where) {
|
|
1692
|
+
if (overflowsToInfinity(text)) {
|
|
1693
|
+
this.report.warnOnce(
|
|
1694
|
+
"precision",
|
|
1695
|
+
PRECISION_CODE,
|
|
1696
|
+
`weight ${text.trim()} is beyond the double range and is stored as Infinity`,
|
|
1697
|
+
where,
|
|
1698
|
+
`${PRECISION_CODE}:weight`
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1473
1701
|
}
|
|
1474
1702
|
/**
|
|
1475
1703
|
* A child of `<edge>`.
|
|
@@ -1477,8 +1705,9 @@ class GexfReader {
|
|
|
1477
1705
|
* @param local - its local name
|
|
1478
1706
|
* @param attrs - its attributes
|
|
1479
1707
|
* @param line - the line
|
|
1708
|
+
* @param ns - the element's namespace
|
|
1480
1709
|
*/
|
|
1481
|
-
startInEdge(name, local, attrs, line) {
|
|
1710
|
+
startInEdge(name, local, attrs, line, ns) {
|
|
1482
1711
|
const { edge } = this;
|
|
1483
1712
|
if (edge === null) {
|
|
1484
1713
|
this.ctx.push(
|
|
@@ -1489,6 +1718,7 @@ class GexfReader {
|
|
|
1489
1718
|
}
|
|
1490
1719
|
switch (local) {
|
|
1491
1720
|
case "attvalues":
|
|
1721
|
+
this.attvalueIds.clear();
|
|
1492
1722
|
this.ctx.push(
|
|
1493
1723
|
9
|
|
1494
1724
|
/* Attvalues */
|
|
@@ -1506,6 +1736,10 @@ class GexfReader {
|
|
|
1506
1736
|
case "color":
|
|
1507
1737
|
case "thickness":
|
|
1508
1738
|
case "shape":
|
|
1739
|
+
if (!isViz(name, ns)) {
|
|
1740
|
+
this.unknownElement(name, line);
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1509
1743
|
this.writeViz(name, local, attrs, "edge", edge.index, edge.where);
|
|
1510
1744
|
this.ctx.push(
|
|
1511
1745
|
14
|
|
@@ -1534,6 +1768,7 @@ class GexfReader {
|
|
|
1534
1768
|
14
|
|
1535
1769
|
/* Skip */
|
|
1536
1770
|
);
|
|
1771
|
+
this.checkAttributes("attvalue", attrs, line);
|
|
1537
1772
|
const { report, edge } = this;
|
|
1538
1773
|
const domain = edge === null ? "node" : "edge";
|
|
1539
1774
|
let index;
|
|
@@ -1567,6 +1802,17 @@ class GexfReader {
|
|
|
1567
1802
|
);
|
|
1568
1803
|
return;
|
|
1569
1804
|
}
|
|
1805
|
+
if (!isTimed(attrs)) {
|
|
1806
|
+
if (this.attvalueIds.has(forId)) {
|
|
1807
|
+
report.warning(
|
|
1808
|
+
"validation-error",
|
|
1809
|
+
DUPLICATE_ATTRIBUTE_CODE,
|
|
1810
|
+
`a second static <attvalue for="${forId}"> on one ${domain}; the later value "${value}" is kept`,
|
|
1811
|
+
{ ...valueWhere, element: forId }
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
this.attvalueIds.add(forId);
|
|
1815
|
+
}
|
|
1570
1816
|
try {
|
|
1571
1817
|
if (domain === "edge" && this.weightAttr !== null && this.weightAttr.id === forId) {
|
|
1572
1818
|
if (isTimed(attrs)) {
|
|
@@ -1611,12 +1857,18 @@ class GexfReader {
|
|
|
1611
1857
|
if (edge === null) {
|
|
1612
1858
|
return;
|
|
1613
1859
|
}
|
|
1614
|
-
const weight = parseWeightText(text);
|
|
1860
|
+
const weight = parseWeightText(text, this.report);
|
|
1615
1861
|
if (weight === void 0) {
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1862
|
+
return;
|
|
1863
|
+
}
|
|
1864
|
+
this.checkOverflow(text, where);
|
|
1865
|
+
if (edge.xmlWeight !== null) {
|
|
1866
|
+
this.report.warning(
|
|
1867
|
+
"validation-error",
|
|
1868
|
+
DUPLICATE_ATTRIBUTE_CODE,
|
|
1869
|
+
`the edge has both weight="${edge.xmlWeight}" and a weight attvalue "${text}"; the attvalue is kept`,
|
|
1870
|
+
where
|
|
1871
|
+
);
|
|
1620
1872
|
}
|
|
1621
1873
|
sink.setEdgeWeight(edge.index, weight);
|
|
1622
1874
|
if (edge.mirror !== INVALID_INDEX) {
|
|
@@ -1653,9 +1905,42 @@ class GexfReader {
|
|
|
1653
1905
|
`long value ${text.trim()} of "${attribute.name}" exceeds 2^53 and was rounded`,
|
|
1654
1906
|
where
|
|
1655
1907
|
);
|
|
1908
|
+
} else if (typeof value === "number" && overflowsToInfinity(text)) {
|
|
1909
|
+
this.report.warnOnce(
|
|
1910
|
+
"precision",
|
|
1911
|
+
PRECISION_CODE,
|
|
1912
|
+
`values of "${attribute.name}" beyond the double range (${text.trim()}) are stored as Infinity`,
|
|
1913
|
+
where,
|
|
1914
|
+
`${PRECISION_CODE}:overflow:${attribute.name}`
|
|
1915
|
+
);
|
|
1656
1916
|
}
|
|
1917
|
+
this.checkOptions(attribute, value, where);
|
|
1657
1918
|
this.setCell(domain, attribute.handle, index, value);
|
|
1658
1919
|
}
|
|
1920
|
+
/**
|
|
1921
|
+
* Report (once per attribute) a value outside the `<options>` the attribute declares; the
|
|
1922
|
+
* value is kept.
|
|
1923
|
+
* @param attribute - the declaration
|
|
1924
|
+
* @param value - the parsed value (a list checks each item)
|
|
1925
|
+
* @param where - the value's location
|
|
1926
|
+
*/
|
|
1927
|
+
checkOptions(attribute, value, where) {
|
|
1928
|
+
const { options } = attribute.valueDecl;
|
|
1929
|
+
if (options === void 0 || options.length === 0) {
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
const items = Array.isArray(value) ? value : [value];
|
|
1933
|
+
const outside = items.find((item) => !options.includes(item));
|
|
1934
|
+
if (typeof outside === "string" || typeof outside === "number" || typeof outside === "boolean") {
|
|
1935
|
+
this.report.warnOnce(
|
|
1936
|
+
"validation-error",
|
|
1937
|
+
VALUE_OUTSIDE_OPTIONS_CODE,
|
|
1938
|
+
`"${outside}" is not among the options of attribute "${attribute.name}"; the value is kept`,
|
|
1939
|
+
where,
|
|
1940
|
+
`${VALUE_OUTSIDE_OPTIONS_CODE}:${attribute.name}`
|
|
1941
|
+
);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1659
1944
|
/**
|
|
1660
1945
|
* Append a timed value to the attribute's temporal table (design section 5.10), creating the
|
|
1661
1946
|
* table on first use.
|
|
@@ -1702,6 +1987,9 @@ class GexfReader {
|
|
|
1702
1987
|
}
|
|
1703
1988
|
}
|
|
1704
1989
|
const row = this.temporalRow(attrs, index, value, where);
|
|
1990
|
+
if (row === null) {
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1705
1993
|
if (temporalValue) {
|
|
1706
1994
|
row.push(valueText ?? void 0);
|
|
1707
1995
|
}
|
|
@@ -1733,14 +2021,14 @@ class GexfReader {
|
|
|
1733
2021
|
)
|
|
1734
2022
|
);
|
|
1735
2023
|
}
|
|
1736
|
-
const value = parseWeightText(text);
|
|
2024
|
+
const value = parseWeightText(text, this.report);
|
|
1737
2025
|
if (value === void 0) {
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
2028
|
+
const row = this.temporalRow(attrs, index, value, where);
|
|
2029
|
+
if (row !== null) {
|
|
2030
|
+
sink.addExtensionRow(weightAttr.table, row);
|
|
1742
2031
|
}
|
|
1743
|
-
sink.addExtensionRow(weightAttr.table, this.temporalRow(attrs, index, value, where));
|
|
1744
2032
|
}
|
|
1745
2033
|
/**
|
|
1746
2034
|
* The row of a temporal table for one timed value: element, bounds, value, bound texts, open bits.
|
|
@@ -1748,10 +2036,13 @@ class GexfReader {
|
|
|
1748
2036
|
* @param index - the element's index
|
|
1749
2037
|
* @param value - the parsed value
|
|
1750
2038
|
* @param where - the value's location
|
|
1751
|
-
* @returns the row, without the optional value text
|
|
2039
|
+
* @returns the row, without the optional value text; null when the interval is inverted (recorded)
|
|
1752
2040
|
*/
|
|
1753
2041
|
temporalRow(attrs, index, value, where) {
|
|
1754
2042
|
const bounds = this.readBounds(attrs, where);
|
|
2043
|
+
if (bounds === null) {
|
|
2044
|
+
return null;
|
|
2045
|
+
}
|
|
1755
2046
|
return [
|
|
1756
2047
|
index,
|
|
1757
2048
|
bounds.start.value,
|
|
@@ -1768,7 +2059,7 @@ class GexfReader {
|
|
|
1768
2059
|
* section 5.1); missing bounds are unbounded.
|
|
1769
2060
|
* @param attrs - the attributes
|
|
1770
2061
|
* @param where - the location, for the conflict warning
|
|
1771
|
-
* @returns the bounds and the open bits
|
|
2062
|
+
* @returns the bounds and the open bits; null (recorded as E_BAD_VALUE) when the interval is inverted
|
|
1772
2063
|
*/
|
|
1773
2064
|
readBounds(attrs, where) {
|
|
1774
2065
|
let start = { value: -Infinity, text: null };
|
|
@@ -1778,6 +2069,14 @@ class GexfReader {
|
|
|
1778
2069
|
if (timestamp !== void 0) {
|
|
1779
2070
|
start = parseTimeText(timestamp, this.timeFormat);
|
|
1780
2071
|
end = start;
|
|
2072
|
+
if (attrs.has("start") || attrs.has("end") || attrs.has("startopen") || attrs.has("endopen")) {
|
|
2073
|
+
this.report.warnOnce(
|
|
2074
|
+
"validation-error",
|
|
2075
|
+
TIMESTAMP_CONFLICT_CODE,
|
|
2076
|
+
"both timestamp and start / end are given; start / end set the interval and the timestamp is kept as written",
|
|
2077
|
+
where
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
1781
2080
|
}
|
|
1782
2081
|
const startText = attrs.get("start");
|
|
1783
2082
|
const startOpen = attrs.get("startopen");
|
|
@@ -1801,6 +2100,15 @@ class GexfReader {
|
|
|
1801
2100
|
end = parseTimeText(endOpen, this.timeFormat);
|
|
1802
2101
|
open |= OPEN_END;
|
|
1803
2102
|
}
|
|
2103
|
+
if (start.value > end.value) {
|
|
2104
|
+
this.report.error(
|
|
2105
|
+
"validation-error",
|
|
2106
|
+
BAD_VALUE_CODE,
|
|
2107
|
+
`the interval starts after it ends (${start.text ?? String(start.value)} > ${end.text ?? String(end.value)}); it is not kept`,
|
|
2108
|
+
where
|
|
2109
|
+
);
|
|
2110
|
+
return null;
|
|
2111
|
+
}
|
|
1804
2112
|
return { start, end, open };
|
|
1805
2113
|
}
|
|
1806
2114
|
/**
|
|
@@ -1829,9 +2137,12 @@ class GexfReader {
|
|
|
1829
2137
|
const { sink, report } = this;
|
|
1830
2138
|
if (attrs.has("start") || attrs.has("end") || attrs.has("timestamp") || attrs.has("startopen") || attrs.has("endopen")) {
|
|
1831
2139
|
const bounds = this.readBounds(attrs, where);
|
|
2140
|
+
if (bounds === null) {
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
1832
2143
|
const timestamp = attrs.get("timestamp");
|
|
1833
2144
|
if (timestamp !== void 0) {
|
|
1834
|
-
columns.timestamp.set(sink, report, index,
|
|
2145
|
+
columns.timestamp.set(sink, report, index, parseTimeText(timestamp, this.timeFormat), where);
|
|
1835
2146
|
}
|
|
1836
2147
|
if (attrs.has("start") || attrs.has("startopen")) {
|
|
1837
2148
|
columns.start.set(sink, report, index, bounds.start, where);
|
|
@@ -1878,10 +2189,20 @@ class GexfReader {
|
|
|
1878
2189
|
line: where.line ?? null
|
|
1879
2190
|
});
|
|
1880
2191
|
}
|
|
1881
|
-
|
|
2192
|
+
const pair = [
|
|
1882
2193
|
parseTimeText(items[0], this.timeFormat).value,
|
|
1883
2194
|
parseTimeText(items[1], this.timeFormat).value
|
|
1884
|
-
]
|
|
2195
|
+
];
|
|
2196
|
+
if (pair[0] > pair[1]) {
|
|
2197
|
+
this.report.error(
|
|
2198
|
+
"validation-error",
|
|
2199
|
+
BAD_VALUE_CODE,
|
|
2200
|
+
`interval "${part.trim()}" starts after it ends; it is not kept`,
|
|
2201
|
+
where
|
|
2202
|
+
);
|
|
2203
|
+
continue;
|
|
2204
|
+
}
|
|
2205
|
+
pairs.push(pair);
|
|
1885
2206
|
}
|
|
1886
2207
|
return pairs;
|
|
1887
2208
|
}
|
|
@@ -1901,9 +2222,13 @@ class GexfReader {
|
|
|
1901
2222
|
14
|
|
1902
2223
|
/* Skip */
|
|
1903
2224
|
);
|
|
2225
|
+
this.checkAttributes("spell", attrs, line);
|
|
1904
2226
|
const where = this.spellsWhere ?? { line };
|
|
1905
2227
|
try {
|
|
1906
2228
|
const bounds = this.readBounds(attrs, where);
|
|
2229
|
+
if (bounds === null) {
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
1907
2232
|
this.spellPairs?.push([bounds.start.value, bounds.end.value]);
|
|
1908
2233
|
this.spellOpen.push(bounds.open);
|
|
1909
2234
|
} catch (err) {
|
|
@@ -2024,28 +2349,52 @@ class GexfReader {
|
|
|
2024
2349
|
);
|
|
2025
2350
|
}
|
|
2026
2351
|
/**
|
|
2027
|
-
* Report XML attributes the importer does not read (once per attribute name and
|
|
2352
|
+
* Report XML attributes the importer does not read (once per attribute name and element kind;
|
|
2353
|
+
* beyond MAX_UNKNOWN_ATTRIBUTE_NAMES distinct names per kind the rest are counted and reported
|
|
2354
|
+
* once at the end). Namespace declarations and `xml:` / `xsi:` attributes are not data.
|
|
2028
2355
|
* @param attrs - the element's attributes
|
|
2029
2356
|
* @param known - the attribute names read
|
|
2030
|
-
* @param
|
|
2357
|
+
* @param kind - the element name
|
|
2031
2358
|
* @param where - the element's location
|
|
2032
2359
|
*/
|
|
2033
|
-
checkAttributeNames(attrs, known,
|
|
2360
|
+
checkAttributeNames(attrs, known, kind, where) {
|
|
2361
|
+
if (attrs.size === 0) {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2034
2364
|
for (const key of attrs.keys()) {
|
|
2035
|
-
if (
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
`attribute ${key} of <${domain}> is not GEXF and was ignored`,
|
|
2043
|
-
{ ...where, element: key }
|
|
2044
|
-
);
|
|
2045
|
-
}
|
|
2365
|
+
if (known.has(key) || key === "xmlns" || /^(xmlns|xml|xsi):/.test(key)) {
|
|
2366
|
+
continue;
|
|
2367
|
+
}
|
|
2368
|
+
let names = this.unknownNames.get(kind);
|
|
2369
|
+
if (names === void 0) {
|
|
2370
|
+
names = /* @__PURE__ */ new Set();
|
|
2371
|
+
this.unknownNames.set(kind, names);
|
|
2046
2372
|
}
|
|
2373
|
+
if (names.has(key)) {
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
names.add(key);
|
|
2377
|
+
if (names.size > MAX_UNKNOWN_ATTRIBUTE_NAMES) {
|
|
2378
|
+
this.unknownOverflow.set(kind, (this.unknownOverflow.get(kind) ?? 0) + 1);
|
|
2379
|
+
continue;
|
|
2380
|
+
}
|
|
2381
|
+
this.report.warning(
|
|
2382
|
+
"unsupported",
|
|
2383
|
+
UNKNOWN_XML_ATTRIBUTE_CODE,
|
|
2384
|
+
`attribute ${key} of <${kind}> is not GEXF and was ignored`,
|
|
2385
|
+
{ ...where, element: key }
|
|
2386
|
+
);
|
|
2047
2387
|
}
|
|
2048
2388
|
}
|
|
2389
|
+
/**
|
|
2390
|
+
* Report the XML attributes the importer does not read on an element other than node / edge.
|
|
2391
|
+
* @param kind - the element's local name (a key of ELEMENT_ATTRIBUTES)
|
|
2392
|
+
* @param attrs - its attributes
|
|
2393
|
+
* @param line - the line
|
|
2394
|
+
*/
|
|
2395
|
+
checkAttributes(kind, attrs, line) {
|
|
2396
|
+
this.checkAttributeNames(attrs, ELEMENT_ATTRIBUTES[kind] ?? /* @__PURE__ */ new Set(), kind, { line });
|
|
2397
|
+
}
|
|
2049
2398
|
/**
|
|
2050
2399
|
* Write one cell of a domain.
|
|
2051
2400
|
* @param domain - node or edge
|
|
@@ -2087,6 +2436,9 @@ class GexfReader {
|
|
|
2087
2436
|
}
|
|
2088
2437
|
}
|
|
2089
2438
|
}
|
|
2439
|
+
function isViz(name, ns) {
|
|
2440
|
+
return isVizNamespace(ns) || ns === null && name.startsWith("viz:");
|
|
2441
|
+
}
|
|
2090
2442
|
function edgeElement(source, target) {
|
|
2091
2443
|
return `${source ?? "?"}->${target ?? "?"}`;
|
|
2092
2444
|
}
|
|
@@ -2122,7 +2474,7 @@ function parseColor(attrs) {
|
|
|
2122
2474
|
if (hex !== void 0 && !attrs.has("r")) {
|
|
2123
2475
|
const digits = hex.startsWith("#") ? hex.slice(1) : hex;
|
|
2124
2476
|
if (!/^[0-9a-fA-F]{6}$/.test(digits)) {
|
|
2125
|
-
throw new GraphFormatError("E_COLUMN_TYPE", `viz hex="${hex}" is not a #RRGGBB
|
|
2477
|
+
throw new GraphFormatError("E_COLUMN_TYPE", `viz hex="${hex}" is not a #RRGGBB color`, {
|
|
2126
2478
|
attribute: "hex"
|
|
2127
2479
|
});
|
|
2128
2480
|
}
|
|
@@ -2139,7 +2491,7 @@ function parseColor(attrs) {
|
|
|
2139
2491
|
}
|
|
2140
2492
|
const XML_START = /^\uFEFF?\s*</;
|
|
2141
2493
|
function sniffGexf(head) {
|
|
2142
|
-
const text =
|
|
2494
|
+
const text = sniffXmlText(head);
|
|
2143
2495
|
if (!XML_START.test(text)) {
|
|
2144
2496
|
return 0;
|
|
2145
2497
|
}
|
|
@@ -2163,6 +2515,7 @@ function resolveGexfOptions(options) {
|
|
|
2163
2515
|
}
|
|
2164
2516
|
const gexfImporter = Object.freeze({
|
|
2165
2517
|
format: GEXF_FORMAT,
|
|
2518
|
+
options: Object.freeze(["viz"]),
|
|
2166
2519
|
extensions: Object.freeze([".gexf"]),
|
|
2167
2520
|
mimeTypes: Object.freeze(["application/gexf+xml", "application/xml", "text/xml"]),
|
|
2168
2521
|
sniff: sniffGexf,
|
|
@@ -2187,10 +2540,13 @@ const gexfImporter = Object.freeze({
|
|
|
2187
2540
|
const reader = new GexfReader(sink, report, resolved, viz);
|
|
2188
2541
|
try {
|
|
2189
2542
|
await tokenizeXml(
|
|
2190
|
-
textChunks(input, report, { ...resolved, declaredEncoding: xmlDeclaredEncoding }),
|
|
2543
|
+
textChunks(input, report, { ...resolved, declaredEncoding: xmlDeclaredEncoding, xml: true }),
|
|
2191
2544
|
reader
|
|
2192
2545
|
);
|
|
2193
2546
|
} catch (err) {
|
|
2547
|
+
if (err instanceof XmlEmptyInputError) {
|
|
2548
|
+
report.fail(EMPTY_INPUT_CODE, "the input is empty (no markup at all)", { line: err.line });
|
|
2549
|
+
}
|
|
2194
2550
|
if (err instanceof XmlSyntaxError) {
|
|
2195
2551
|
report.fail(XML_SYNTAX_CODE, err.message, { line: err.line });
|
|
2196
2552
|
}
|
|
@@ -2210,25 +2566,41 @@ const GEXF_LOSS = Object.freeze({
|
|
|
2210
2566
|
LIST_SEPARATOR: "W_LIST_SEPARATOR",
|
|
2211
2567
|
/** A role column of a shape GEXF cannot map (a string `start`, a 2-component color); written as a plain attribute. */
|
|
2212
2568
|
ROLE_SHAPE: "W_ROLE_SHAPE",
|
|
2213
|
-
/** A temporal extension table without the element / start / end / value columns
|
|
2569
|
+
/** A temporal extension table without the element / start / end / value columns. */
|
|
2214
2570
|
TEMPORAL_TABLE_SHAPE: "W_TEMPORAL_TABLE_SHAPE",
|
|
2215
|
-
/** An attribute
|
|
2571
|
+
/** An attribute's name is one GEXF reserves, so a GEXF import would give it another name. */
|
|
2216
2572
|
ATTRIBUTE_RENAMED: "W_ATTRIBUTE_RENAMED",
|
|
2217
2573
|
/** A cell, default or option the declared type cannot express (skipped). */
|
|
2218
2574
|
VALUE_UNWRITABLE: "W_VALUE_UNWRITABLE",
|
|
2219
|
-
/**
|
|
2575
|
+
/**
|
|
2576
|
+
* An attribute type that this GEXF version does not have (GEXF 1.2 has no date, dateTime or typed lists) is
|
|
2577
|
+
* written as the nearest type it has.
|
|
2578
|
+
*/
|
|
2220
2579
|
DECLARED_TYPE: "W_DECLARED_TYPE",
|
|
2221
|
-
/**
|
|
2580
|
+
/**
|
|
2581
|
+
* A node id that reads back as a different type: a number that is not an integer comes back as text, and text that
|
|
2582
|
+
* looks like an integer ("42") comes back as a number, unless you read the file with `ids: "string"` or `ids:
|
|
2583
|
+
* "keep"`.
|
|
2584
|
+
*/
|
|
2222
2585
|
ID_TEXT_TYPE: LOSS.ID_TEXT_TYPE,
|
|
2223
2586
|
/** A numeric edge id column: GEXF edge ids read back as strings. */
|
|
2224
2587
|
EDGE_ID_TEXT: "W_GEXF_EDGE_ID_TEXT",
|
|
2225
|
-
/**
|
|
2588
|
+
/**
|
|
2589
|
+
* A visual attribute (position, color, size, thickness) is stored at more precision than GEXF keeps; it reads back
|
|
2590
|
+
* as a 32-bit float.
|
|
2591
|
+
*/
|
|
2226
2592
|
VIZ_DTYPE: "W_GEXF_VIZ_DTYPE",
|
|
2227
|
-
/**
|
|
2593
|
+
/**
|
|
2594
|
+
* An attribute named `weight` without the weight role reads back as the edge weight, because GEXF reads weights
|
|
2595
|
+
* from `weight` by default.
|
|
2596
|
+
*/
|
|
2228
2597
|
WEIGHT_KEY_CLASH: LOSS.WEIGHT_KEY_CLASH,
|
|
2229
|
-
/**
|
|
2598
|
+
/**
|
|
2599
|
+
* A text attribute stored as a dictionary, without a declared list of allowed values, reads back with its distinct
|
|
2600
|
+
* values as that list.
|
|
2601
|
+
*/
|
|
2230
2602
|
OPTIONS_GAINED: LOSS.OPTIONS_GAINED,
|
|
2231
|
-
/** A
|
|
2603
|
+
/** A text value holds a character XML 1.0 forbids (most control characters); the save fails with E_COLUMN_TYPE. */
|
|
2232
2604
|
XML_ILLEGAL_CHAR: LOSS.XML_ILLEGAL_CHAR
|
|
2233
2605
|
});
|
|
2234
2606
|
const DTYPES_KEPT = ["f32", "f64", "i32", "bool", "dict", "string"];
|
|
@@ -2284,7 +2656,8 @@ function planExport(snapshot, options) {
|
|
|
2284
2656
|
temporalText: true,
|
|
2285
2657
|
positionDtype: "f32",
|
|
2286
2658
|
roles: MAPPED_ROLES,
|
|
2287
|
-
|
|
2659
|
+
// GEXF 1.2 has no edge kind: the kind column is dropped (W_GEXF_KIND_DROPPED), not renamed
|
|
2660
|
+
roleNames: version === "1.2" ? ROLE_NAMES_1_2 : ROLE_NAMES
|
|
2288
2661
|
})
|
|
2289
2662
|
];
|
|
2290
2663
|
const note = (code, message, column = null, count = null) => {
|
|
@@ -2301,7 +2674,7 @@ function planExport(snapshot, options) {
|
|
|
2301
2674
|
if (typeChanges > 0) {
|
|
2302
2675
|
note(
|
|
2303
2676
|
GEXF_LOSS.ID_TEXT_TYPE,
|
|
2304
|
-
`${typeChanges} node id(
|
|
2677
|
+
`${typeChanges} node id${plural(typeChanges)} ${agree(typeChanges, "changes", "change")} type when read back under ids: "canonical" (string ids that are integer text, non-integer numbers); the file's idtype is not honored by the importer`,
|
|
2305
2678
|
null,
|
|
2306
2679
|
typeChanges
|
|
2307
2680
|
);
|
|
@@ -2461,6 +2834,9 @@ const ROLE_NAMES = Object.freeze({
|
|
|
2461
2834
|
parent: NODE_COLUMNS.parent,
|
|
2462
2835
|
parents: NODE_COLUMNS.parents
|
|
2463
2836
|
});
|
|
2837
|
+
const ROLE_NAMES_1_2 = Object.freeze(
|
|
2838
|
+
Object.fromEntries(Object.entries(ROLE_NAMES).filter(([role]) => role !== "kind"))
|
|
2839
|
+
);
|
|
2464
2840
|
function collectRoles(table, domain, note) {
|
|
2465
2841
|
const companions = /* @__PURE__ */ new Map();
|
|
2466
2842
|
const roles = {
|
|
@@ -2792,7 +3168,7 @@ function collectAttributes(snapshot, domain, roles, tables, version, note) {
|
|
|
2792
3168
|
if (domain === "edge" && column !== null && column.meta.role === null && title === DEFAULT_WEIGHT_TITLE) {
|
|
2793
3169
|
note(
|
|
2794
3170
|
GEXF_LOSS.WEIGHT_KEY_CLASH,
|
|
2795
|
-
`edge column "${name}" is written as an attribute titled "${title}", which the importer reads as
|
|
3171
|
+
`edge column "${name}" is written as an attribute titled "${title}", which the importer reads as the edge weight (weightFrom); it reads back as the weight, not as a column`,
|
|
2796
3172
|
name,
|
|
2797
3173
|
column.length - column.nullCount
|
|
2798
3174
|
);
|
|
@@ -2929,7 +3305,7 @@ function declaredTexts(column, domain, typed, version, note) {
|
|
|
2929
3305
|
if (count > 0) {
|
|
2930
3306
|
note(
|
|
2931
3307
|
GEXF_LOSS.LIST_SEPARATOR,
|
|
2932
|
-
`${domain} column "${name}": ${count} row(
|
|
3308
|
+
`${domain} column "${name}": ${count} row${plural(count)} ${agree(count, "holds", "hold")} an item containing "|", the 1.2 list separator`,
|
|
2933
3309
|
name,
|
|
2934
3310
|
count
|
|
2935
3311
|
);
|
|
@@ -3426,6 +3802,7 @@ function graphExtraText(snapshot, key) {
|
|
|
3426
3802
|
}
|
|
3427
3803
|
const gexfExporter = Object.freeze({
|
|
3428
3804
|
format: GEXF_FORMAT,
|
|
3805
|
+
options: Object.freeze(["version"]),
|
|
3429
3806
|
capabilities: CAPABILITIES_1_3,
|
|
3430
3807
|
/**
|
|
3431
3808
|
* Pre-flight: what export() would lose.
|
|
@@ -3457,38 +3834,71 @@ const gexfExporter = Object.freeze({
|
|
|
3457
3834
|
});
|
|
3458
3835
|
const GEXF_1_2_CAPABILITIES = CAPABILITIES_1_2;
|
|
3459
3836
|
const GEXF_ISSUE = Object.freeze({
|
|
3460
|
-
|
|
3837
|
+
...INPUT_ISSUE,
|
|
3838
|
+
...ELEMENT_ISSUE,
|
|
3839
|
+
/**
|
|
3840
|
+
* A value that does not parse as the type its attribute declares ("x" in an integer attribute). The value is
|
|
3841
|
+
* left unset; the node or edge is kept.
|
|
3842
|
+
*/
|
|
3843
|
+
COLUMN_TYPE: COLUMN_TYPE_CODE,
|
|
3844
|
+
/** The XML is not well-formed. The import stops. */
|
|
3461
3845
|
XML_SYNTAX: XML_SYNTAX_CODE,
|
|
3462
|
-
/** The input
|
|
3846
|
+
/** The input is not valid UTF-8. The import stops. */
|
|
3463
3847
|
INVALID_UTF8: INVALID_UTF8_CODE,
|
|
3464
|
-
/**
|
|
3848
|
+
/**
|
|
3849
|
+
* Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
|
|
3850
|
+
* `encoding` option). The import stops.
|
|
3851
|
+
*/
|
|
3465
3852
|
INVALID_ENCODING: INVALID_ENCODING_CODE,
|
|
3466
3853
|
/** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
|
|
3467
3854
|
ENCODING_FALLBACK: ENCODING_FALLBACK_CODE,
|
|
3468
3855
|
/** A declared encoding the platform cannot decode was ignored. */
|
|
3469
3856
|
UNKNOWN_ENCODING: UNKNOWN_ENCODING_CODE,
|
|
3470
|
-
/**
|
|
3857
|
+
/** A declared encoding the byte order mark contradicts (the mark wins). */
|
|
3858
|
+
ENCODING_CONFLICT: ENCODING_CONFLICT_CODE,
|
|
3859
|
+
/** The input holds no XML at all: it is empty, whitespace or a byte order mark only. The import stops. */
|
|
3860
|
+
EMPTY_INPUT: EMPTY_INPUT_CODE,
|
|
3861
|
+
/** The root element is not `<gexf>`. The import stops. */
|
|
3471
3862
|
NOT_GEXF: NOT_GEXF_CODE,
|
|
3472
|
-
/** The document has no `<graph
|
|
3863
|
+
/** The document has no `<graph>`. The import stops. */
|
|
3473
3864
|
NO_GRAPH: NO_GRAPH_CODE,
|
|
3865
|
+
/**
|
|
3866
|
+
* The file holds more than one `<graph>` element; their nodes and edges are merged into one graph.
|
|
3867
|
+
* `importAllGraphs()` reads every one.
|
|
3868
|
+
*/
|
|
3869
|
+
MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
|
|
3474
3870
|
/** `<edges>` without `<nodes>`. */
|
|
3475
3871
|
MISSING_NODES: MISSING_NODES_CODE,
|
|
3476
3872
|
/** A node without an id. */
|
|
3477
3873
|
MISSING_ID: MISSING_ID_CODE,
|
|
3478
3874
|
/** An edge without a source or target. */
|
|
3479
3875
|
MISSING_ENDPOINT: MISSING_ENDPOINT_CODE,
|
|
3876
|
+
/** An edge endpoint that names no declared node (addMissingNodes false, the GEXF default). */
|
|
3877
|
+
UNKNOWN_NODE: "E_UNKNOWN_NODE",
|
|
3480
3878
|
/** An edge `type` outside directed / undirected / mutual. */
|
|
3481
3879
|
EDGE_TYPE: EDGE_TYPE_CODE,
|
|
3482
|
-
/** A `pid` / `<parent for>` naming an unknown node. */
|
|
3880
|
+
/** A `pid` / `<parent for>` naming an unknown node, a `<parent>` without for, or the children of a skipped node. */
|
|
3483
3881
|
UNKNOWN_PARENT: UNKNOWN_PARENT_CODE,
|
|
3882
|
+
/** A `pid` / nested containment that would close a parent cycle; that link is dropped. */
|
|
3883
|
+
PARENT_CYCLE: PARENT_CYCLE_CODE,
|
|
3884
|
+
/** An inverted interval (start after end) of an element, a spell or a value; it is not kept. */
|
|
3885
|
+
BAD_VALUE: BAD_VALUE_CODE,
|
|
3484
3886
|
/** An `<attributes class>` outside node / edge. */
|
|
3485
3887
|
ATTRIBUTES_CLASS: ATTRIBUTES_CLASS_CODE,
|
|
3486
3888
|
/** An `<attribute>` without an id. */
|
|
3487
3889
|
ATTRIBUTE_ID: ATTRIBUTE_ID_CODE,
|
|
3488
3890
|
/** A `<graph>` header attribute with an unknown value. */
|
|
3489
3891
|
HEADER_VALUE: HEADER_VALUE_CODE,
|
|
3490
|
-
/**
|
|
3892
|
+
/**
|
|
3893
|
+
* A node or edge count the file announces is too large to reserve room for; it is ignored and the elements are
|
|
3894
|
+
* read as they come.
|
|
3895
|
+
*/
|
|
3491
3896
|
COUNT_HINT: COUNT_HINT_CODE,
|
|
3897
|
+
/**
|
|
3898
|
+
* A `count` attribute disagrees with the number of nodes or edges actually in its section. The elements are read
|
|
3899
|
+
* as they are.
|
|
3900
|
+
*/
|
|
3901
|
+
COUNT_MISMATCH: COUNT_MISMATCH_CODE,
|
|
3492
3902
|
/** A node id declared twice. */
|
|
3493
3903
|
DUPLICATE_NODE: DUPLICATE_NODE_CODE,
|
|
3494
3904
|
/** An edge id declared twice (the second edge is skipped). */
|
|
@@ -3503,9 +3913,15 @@ const GEXF_ISSUE = Object.freeze({
|
|
|
3503
3913
|
BAD_DEFAULT: BAD_DEFAULT_CODE,
|
|
3504
3914
|
/** Options that do not parse as the declared type. */
|
|
3505
3915
|
BAD_OPTIONS: BAD_OPTIONS_CODE,
|
|
3506
|
-
/**
|
|
3916
|
+
/**
|
|
3917
|
+
* An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example
|
|
3918
|
+
* two attributes declared with the same name.
|
|
3919
|
+
*/
|
|
3507
3920
|
COLUMN_RENAMED: COLUMN_RENAMED_CODE,
|
|
3508
|
-
/**
|
|
3921
|
+
/**
|
|
3922
|
+
* You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
|
|
3923
|
+
* a plain attribute.
|
|
3924
|
+
*/
|
|
3509
3925
|
ROLE_TAKEN: ROLE_TAKEN_CODE,
|
|
3510
3926
|
/** An `<attvalue for>` naming an undeclared attribute. */
|
|
3511
3927
|
UNKNOWN_ATTRIBUTE: UNKNOWN_ATTRIBUTE_CODE,
|
|
@@ -3513,13 +3929,13 @@ const GEXF_ISSUE = Object.freeze({
|
|
|
3513
3929
|
ATTVALUE_SHAPE: ATTVALUE_SHAPE_CODE,
|
|
3514
3930
|
/** A timed value on an attribute of a static group. */
|
|
3515
3931
|
TIMED_VALUE_ON_STATIC: TIMED_STATIC_CODE,
|
|
3516
|
-
/**
|
|
3932
|
+
/** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
|
|
3517
3933
|
PRECISION: PRECISION_CODE,
|
|
3518
|
-
/** Two id texts
|
|
3934
|
+
/** Two different id texts became the same number because `ids` is "number", so their nodes were merged. */
|
|
3519
3935
|
ID_MERGED: ID_MERGED_CODE,
|
|
3520
3936
|
/** The XML weight attribute ignored under weightFrom null. */
|
|
3521
3937
|
WEIGHT_IGNORED: WEIGHT_IGNORED_CODE,
|
|
3522
|
-
/**
|
|
3938
|
+
/** Viz elements skipped under viz: false. */
|
|
3523
3939
|
VIZ_SKIPPED: VIZ_SKIPPED_CODE,
|
|
3524
3940
|
/** A 1.2 dynamic viz element whose bounds were dropped. */
|
|
3525
3941
|
VIZ_DYNAMIC_DROPPED: VIZ_DYNAMIC_CODE,
|
|
@@ -3529,19 +3945,35 @@ const GEXF_ISSUE = Object.freeze({
|
|
|
3529
3945
|
VIZ_VALUE: VIZ_VALUE_CODE,
|
|
3530
3946
|
/** Both `start` and `startopen` (or `end` and `endopen`) on one element. */
|
|
3531
3947
|
OPEN_BOUND_CONFLICT: OPEN_BOUND_CONFLICT_CODE,
|
|
3532
|
-
/**
|
|
3948
|
+
/** Both `timestamp` and `start` / `end` on one element or value. */
|
|
3949
|
+
TIMESTAMP_CONFLICT: TIMESTAMP_CONFLICT_CODE,
|
|
3950
|
+
/** A value outside the declared `<options>` (kept). */
|
|
3951
|
+
VALUE_OUTSIDE_OPTIONS: VALUE_OUTSIDE_OPTIONS_CODE,
|
|
3952
|
+
/** An element GEXF does not define at that place was skipped. */
|
|
3533
3953
|
UNKNOWN_ELEMENT: UNKNOWN_ELEMENT_CODE,
|
|
3954
|
+
/** An XML attribute GEXF does not define on that element was ignored. */
|
|
3955
|
+
UNKNOWN_XML_ATTRIBUTE: UNKNOWN_XML_ATTRIBUTE_CODE,
|
|
3534
3956
|
/** Text where GEXF allows only elements was ignored. */
|
|
3535
3957
|
STRAY_TEXT: STRAY_TEXT_CODE,
|
|
3536
|
-
/**
|
|
3958
|
+
/** You set an option this format does not use; it had no effect. The message names the option. */
|
|
3537
3959
|
OPTION_IGNORED: OPTION_IGNORED_CODE,
|
|
3538
|
-
/**
|
|
3960
|
+
/**
|
|
3961
|
+
* You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
|
|
3962
|
+
* `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
|
|
3963
|
+
*/
|
|
3539
3964
|
SINK_OPTION: SINK_OPTION_CODE,
|
|
3540
|
-
/**
|
|
3965
|
+
/**
|
|
3966
|
+
* You read into a graph builder whose direction is already set, or which already holds edges, so the file is read
|
|
3967
|
+
* with the builder's direction instead of its own.
|
|
3968
|
+
*/
|
|
3541
3969
|
DIRECTION_REFUSED: DIRECTION_REFUSED_CODE,
|
|
3542
|
-
/** Edges
|
|
3970
|
+
/** Edges of the other direction were read with the direction `onMixedDirection` chose. */
|
|
3543
3971
|
DIRECTION_FORCED: DIRECTION_FORCED_CODE,
|
|
3544
|
-
/**
|
|
3972
|
+
/**
|
|
3973
|
+
* The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
|
|
3974
|
+
* format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
|
|
3975
|
+
* it anyway.
|
|
3976
|
+
*/
|
|
3545
3977
|
MIXED_DIRECTION: MIXED_DIRECTION_CODE
|
|
3546
3978
|
});
|
|
3547
3979
|
export {
|