@graphty/graph-io 0.3.24 → 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
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
|
|
2
|
-
import {
|
|
3
|
-
import { i as isPajekLabel, q as quotePajekLabel } from "./escape-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { i as
|
|
7
|
-
import { j as joinText, e as encodeChunks } from "./writer-C7flM-Ih.js";
|
|
2
|
+
import { L as LOSS, r as resolveExportOptions, aE as sanitizeIds, a as checkCapabilities, p as pairFolding, b as plural, $ as agree, c as capabilities, a9 as idText, e as explicitWeights, aF as formatDecimal, aa as formatF32, aG as formatInteger, aH as canonicalId, P as PRECISION_CODE, o as DUPLICATE_ATTRIBUTE_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, ay as RENAMED_CODE, I as ID_MERGED_CODE, n as DUPLICATE_NODE_CODE, ak as SYNTAX_CODE, ae as AMBIGUOUS_GRAPH_NAME_CODE, af as GRAPH_NOT_FOUND_CODE, l as MULTIPLE_GRAPHS_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE, al as resolveImportOptions, a8 as ImportReportBuilder, an as reportUnusedOptions, az as LineReader, am as throwIfAborted, ap as graphChosen, ao as reportSinkOptions, aq as DirectionResolver, ar as IdCoercer, a0 as uniqueColumnName, a1 as declareResolved, aI as coerceIdText, aJ as survivesF32, aK as isWeightField, aL as parseWeightText } from "./export-BTI4yQgy.js";
|
|
3
|
+
import { i as isPajekLabel, q as quotePajekLabel } from "./escape-D0g6NNUy.js";
|
|
4
|
+
import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, a as isNumericText, T as TextCellWriter } from "./text-DmcUs5_Q.js";
|
|
5
|
+
import { j as joinText, e as encodeChunks } from "./writer-DxjgHwSe.js";
|
|
6
|
+
import { i as importChosenGraph } from "./choose-BbJI55dx.js";
|
|
8
7
|
const LABEL_COLUMN = "label";
|
|
9
8
|
const POSITION_COLUMN = "position";
|
|
10
9
|
const SHAPE_COLUMN = "shape";
|
|
@@ -42,46 +41,103 @@ const SECTION_KINDS = /* @__PURE__ */ new Map([
|
|
|
42
41
|
]);
|
|
43
42
|
const INTEGER_TEXT = /^[+-]?[0-9]+$/;
|
|
44
43
|
const TIME_POINT = /^(\*|[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)(?:-(\*|[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?))?$/;
|
|
45
|
-
function tokenize(line) {
|
|
46
|
-
const tokens =
|
|
47
|
-
let
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
function tokenize(line, notes) {
|
|
45
|
+
const tokens = new LineTokens(line, notes);
|
|
46
|
+
let i = 0;
|
|
47
|
+
while (i < line.length) {
|
|
48
|
+
i = tokens.step(i);
|
|
49
|
+
}
|
|
50
|
+
return tokens.finish();
|
|
51
|
+
}
|
|
52
|
+
class LineTokens {
|
|
53
|
+
/**
|
|
54
|
+
* Start a line.
|
|
55
|
+
* @param line - the line
|
|
56
|
+
* @param notes - set to what the line holds beyond its tokens, when given
|
|
57
|
+
*/
|
|
58
|
+
constructor(line, notes) {
|
|
59
|
+
this.line = line;
|
|
60
|
+
this.notes = notes;
|
|
61
|
+
this.tokens = [];
|
|
62
|
+
this.current = "";
|
|
63
|
+
this.started = false;
|
|
64
|
+
this.quoted = false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Read the character at `i`.
|
|
68
|
+
* @param i - its index
|
|
69
|
+
* @returns the index of the next character to read
|
|
70
|
+
*/
|
|
71
|
+
step(i) {
|
|
72
|
+
const c = this.line.codePointAt(i);
|
|
52
73
|
if (c === 34) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
continue;
|
|
74
|
+
this.quote(i);
|
|
75
|
+
return i + 1;
|
|
56
76
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
i = close;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
77
|
+
const close = !this.quoted && !this.started && c === 91 ? this.intervalEnd(i) : -1;
|
|
78
|
+
if (close > 0) {
|
|
79
|
+
this.current += this.line.slice(i, close + 1);
|
|
80
|
+
this.started = true;
|
|
81
|
+
return close + 1;
|
|
65
82
|
}
|
|
66
|
-
if (!quoted && (c
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
current = "";
|
|
70
|
-
started = false;
|
|
71
|
-
}
|
|
72
|
-
continue;
|
|
83
|
+
if (!this.quoted && isBlank(c)) {
|
|
84
|
+
this.endToken();
|
|
85
|
+
return i + 1;
|
|
73
86
|
}
|
|
74
|
-
current += line[i];
|
|
75
|
-
started = true;
|
|
87
|
+
this.current += this.line[i];
|
|
88
|
+
this.started = true;
|
|
89
|
+
return i + 1;
|
|
76
90
|
}
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
/**
|
|
92
|
+
* The tokens of the line.
|
|
93
|
+
* @returns them, or null when a quote is not closed
|
|
94
|
+
*/
|
|
95
|
+
finish() {
|
|
96
|
+
if (this.quoted) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
this.endToken();
|
|
100
|
+
return this.tokens;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Open or close a quote. One that opens inside a token, or closes with more of the token after
|
|
104
|
+
* it, is noted.
|
|
105
|
+
* @param i - the quote's index
|
|
106
|
+
*/
|
|
107
|
+
quote(i) {
|
|
108
|
+
const next = this.line.codePointAt(i + 1);
|
|
109
|
+
const joined = this.quoted ? i + 1 < this.line.length && !isBlank(next) : this.started;
|
|
110
|
+
if (joined && this.notes !== void 0) {
|
|
111
|
+
this.notes.oddQuote = true;
|
|
112
|
+
}
|
|
113
|
+
this.quoted = !this.quoted;
|
|
114
|
+
this.started = true;
|
|
79
115
|
}
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Where a `[` that starts a token is closed, when no other `[` comes first.
|
|
118
|
+
* @param i - the index of the `[`
|
|
119
|
+
* @returns the index of its `]`, or -1
|
|
120
|
+
*/
|
|
121
|
+
intervalEnd(i) {
|
|
122
|
+
const close = this.line.indexOf("]", i);
|
|
123
|
+
return close > i && this.line.lastIndexOf("[", close) === i ? close : -1;
|
|
82
124
|
}
|
|
83
|
-
|
|
125
|
+
/** End the token being read, if any. */
|
|
126
|
+
endToken() {
|
|
127
|
+
if (this.started) {
|
|
128
|
+
this.tokens.push(this.current);
|
|
129
|
+
this.current = "";
|
|
130
|
+
this.started = false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function isBlank(c) {
|
|
135
|
+
return c === 32 || c === 9 || c === 13 || c === 12 || c === 11;
|
|
136
|
+
}
|
|
137
|
+
function isProjectObject(keyword) {
|
|
138
|
+
return PROJECT_OBJECTS.has(keyword.toLowerCase());
|
|
84
139
|
}
|
|
140
|
+
const PROJECT_OBJECTS = /* @__PURE__ */ new Set(["permutation", "cluster", "hierarchy"]);
|
|
85
141
|
function isCommentOrBlank(line) {
|
|
86
142
|
for (let i = 0; i < line.length; i++) {
|
|
87
143
|
const c = line.charCodeAt(i);
|
|
@@ -187,8 +243,11 @@ function parseIntervals(token) {
|
|
|
187
243
|
if (match === null) {
|
|
188
244
|
throw new Error(`malformed time interval ${token}: "${part}" is not a-b, a-* or a`);
|
|
189
245
|
}
|
|
190
|
-
const
|
|
191
|
-
|
|
246
|
+
const [, startText, endText] = match;
|
|
247
|
+
if (startText === "*" && endText === void 0) {
|
|
248
|
+
throw new Error(`malformed time interval ${token}: "*" alone is not a time point`);
|
|
249
|
+
}
|
|
250
|
+
const start = startText === "*" ? -Infinity : Number(startText);
|
|
192
251
|
let end;
|
|
193
252
|
if (endText === void 0) {
|
|
194
253
|
end = start;
|
|
@@ -197,21 +256,28 @@ function parseIntervals(token) {
|
|
|
197
256
|
} else {
|
|
198
257
|
end = Number(endText);
|
|
199
258
|
}
|
|
259
|
+
if (startText !== "*" && !Number.isFinite(start) || endText !== void 0 && endText !== "*" && !Number.isFinite(end)) {
|
|
260
|
+
throw new Error(`malformed time interval ${token}: "${part}" is beyond the number range`);
|
|
261
|
+
}
|
|
200
262
|
if (start > end) {
|
|
201
|
-
throw new Error(`malformed time interval ${token}: ${
|
|
263
|
+
throw new Error(`malformed time interval ${token}: ${startText} is after ${endText ?? ""}`);
|
|
202
264
|
}
|
|
203
265
|
spells.push([start, end]);
|
|
204
266
|
}
|
|
205
267
|
return spells;
|
|
206
268
|
}
|
|
207
|
-
const CHARACTER_REFERENCE = /&#(?:[xX]([
|
|
208
|
-
function decodeCharacterReferences(text) {
|
|
269
|
+
const CHARACTER_REFERENCE = /&#(?:[xX]([\da-fA-F]+)|(\d+));/g;
|
|
270
|
+
function decodeCharacterReferences(text, onUnknown) {
|
|
209
271
|
if (!text.includes("&#")) {
|
|
210
272
|
return text;
|
|
211
273
|
}
|
|
212
274
|
return text.replace(CHARACTER_REFERENCE, (whole, hex, dec) => {
|
|
213
275
|
const code = hex === void 0 ? Number(dec) : Number.parseInt(hex, 16);
|
|
214
|
-
|
|
276
|
+
if (code <= 1114111) {
|
|
277
|
+
return String.fromCodePoint(code);
|
|
278
|
+
}
|
|
279
|
+
onUnknown?.(whole);
|
|
280
|
+
return whole;
|
|
215
281
|
});
|
|
216
282
|
}
|
|
217
283
|
function encodeCharacterReferences(text) {
|
|
@@ -233,42 +299,63 @@ function formatIntervals(spells) {
|
|
|
233
299
|
return `[${parts.join(",")}]`;
|
|
234
300
|
}
|
|
235
301
|
function isParameterKey(text) {
|
|
236
|
-
if (text.length === 0 || /[\s"]/.test(text) || text.startsWith("[") || text.startsWith("*")) {
|
|
302
|
+
if (text.length === 0 || /[\s"]/.test(text) || text.startsWith("[") || text.startsWith("*") || text.startsWith("%")) {
|
|
237
303
|
return false;
|
|
238
304
|
}
|
|
239
305
|
if (isShapeKeyword(text)) {
|
|
240
306
|
return false;
|
|
241
307
|
}
|
|
242
|
-
return !/^[+-]?(
|
|
308
|
+
return !/^[+-]?(\.\d|\d)/.test(text) && !/^[+-]?(?:nan|inf|infinity)$/i.test(text);
|
|
243
309
|
}
|
|
244
310
|
const PAJEK_LOSS = Object.freeze({
|
|
245
|
-
/**
|
|
311
|
+
/**
|
|
312
|
+
* A label or text value holds a double quote or a line break, which Pajek cannot write; the save fails with
|
|
313
|
+
* E_UNSUPPORTED.
|
|
314
|
+
*/
|
|
246
315
|
TEXT: "E_PAJEK_TEXT",
|
|
247
316
|
/** A column whose name cannot be a parameter key (whitespace, a quote, numeric, a shape keyword); skipped. */
|
|
248
317
|
KEY_DROPPED: "W_PAJEK_KEY_DROPPED",
|
|
249
|
-
/**
|
|
318
|
+
/**
|
|
319
|
+
* The node label attribute holds numbers or other values that are not text; they are written as text and read back
|
|
320
|
+
* as text.
|
|
321
|
+
*/
|
|
250
322
|
LABEL_AS_TEXT: "W_PAJEK_LABEL_AS_TEXT",
|
|
251
|
-
/**
|
|
323
|
+
/** NaN or an infinity is written as the text Infinity or NaN, which reads back as text. */
|
|
252
324
|
NONFINITE_AS_TEXT: "W_PAJEK_NONFINITE_AS_TEXT",
|
|
253
325
|
/** A mutual pair; written as one undirected edge, the mark lost. */
|
|
254
326
|
MUTUAL_AS_UNDIRECTED: LOSS.MUTUAL_AS_UNDIRECTED,
|
|
255
327
|
/** A start / end / timestamp role column; Pajek intervals are written from the spells role only. */
|
|
256
328
|
TEMPORAL_DROPPED: LOSS.TEMPORAL,
|
|
257
|
-
/** A position
|
|
329
|
+
/** A position with other than 2 or 3 coordinates is not written. */
|
|
258
330
|
POSITION_STRIDE: "W_PAJEK_POSITION_STRIDE",
|
|
259
|
-
/**
|
|
331
|
+
/**
|
|
332
|
+
* The graph's two-mode vertex count (`meta.extra.pajek.firstMode`) is not between 0 and the number of nodes, so
|
|
333
|
+
* the file is written as a one-mode network.
|
|
334
|
+
*/
|
|
260
335
|
FIRST_MODE_DROPPED: "W_PAJEK_FIRST_MODE_DROPPED",
|
|
261
|
-
/**
|
|
336
|
+
/** An attribute with a role the format has no place for is written as a plain attribute; the role is lost. */
|
|
262
337
|
ROLE_DROPPED: LOSS.ROLE,
|
|
263
|
-
/**
|
|
338
|
+
/**
|
|
339
|
+
* A `shape` attribute whose value is not one of Pajek's shape names is written as a parameter, and reads back as a
|
|
340
|
+
* plain text attribute.
|
|
341
|
+
*/
|
|
264
342
|
SHAPE_AS_PARAMETER: "W_PAJEK_SHAPE_AS_PARAMETER",
|
|
265
343
|
/** A vertex line with coordinates, a shape or parameters needs a label: the id text is written and reads back as a label. */
|
|
266
344
|
LABEL_GAINED: "W_PAJEK_LABEL_GAINED",
|
|
267
|
-
/**
|
|
345
|
+
/**
|
|
346
|
+
* An attribute without a role is written where the format keeps a role (for example, a `name` column as the label), and
|
|
347
|
+
* reads back with that role.
|
|
348
|
+
*/
|
|
268
349
|
ROLE_ASSUMED: LOSS.ROLE_ASSUMED,
|
|
269
|
-
/**
|
|
350
|
+
/**
|
|
351
|
+
* With `sanitizeIds: "mangle"`: an original id that reads back as a different type, such as the text "7" as the
|
|
352
|
+
* number 7.
|
|
353
|
+
*/
|
|
270
354
|
ID_TEXT_TYPE: LOSS.ID_TEXT_TYPE,
|
|
271
|
-
/**
|
|
355
|
+
/**
|
|
356
|
+
* A text value that reads back as a number or a boolean, because the format does not record that it was text (the
|
|
357
|
+
* text "42" reads back as the number 42).
|
|
358
|
+
*/
|
|
272
359
|
TEXT_INFERRED: LOSS.TEXT_INFERRED
|
|
273
360
|
});
|
|
274
361
|
const SLOT_ROLES = /* @__PURE__ */ new Set(["label"]);
|
|
@@ -453,7 +540,7 @@ function labelNotes(snapshot, nodePlan, notes) {
|
|
|
453
540
|
notes.push(
|
|
454
541
|
note(
|
|
455
542
|
PAJEK_LOSS.LABEL_GAINED,
|
|
456
|
-
`${gained} vertex line(
|
|
543
|
+
`${gained} vertex line${plural(gained)} ${agree(gained, "carries", "carry")} coordinates, a shape or parameters and need a label; the id text is written there and reads back as a label`,
|
|
457
544
|
labels === null ? LABEL_COLUMN : labels.meta.name,
|
|
458
545
|
gained
|
|
459
546
|
)
|
|
@@ -554,7 +641,7 @@ function checkCells(planned, domain, notes) {
|
|
|
554
641
|
notes.push(
|
|
555
642
|
note(
|
|
556
643
|
PAJEK_LOSS.TEXT,
|
|
557
|
-
`${badText} value(
|
|
644
|
+
`${badText} value${plural(badText)} of ${domain} column "${name}" hold a double quote or a line break; Pajek cannot write them`,
|
|
558
645
|
name,
|
|
559
646
|
badText
|
|
560
647
|
)
|
|
@@ -564,7 +651,7 @@ function checkCells(planned, domain, notes) {
|
|
|
564
651
|
notes.push(
|
|
565
652
|
note(
|
|
566
653
|
PAJEK_LOSS.TEXT_INFERRED,
|
|
567
|
-
`${typed} value(
|
|
654
|
+
`${typed} value${plural(typed)} of ${domain} column "${name}" look like numbers or booleans; Pajek parameters are untyped and they read back as such`,
|
|
568
655
|
name,
|
|
569
656
|
typed
|
|
570
657
|
)
|
|
@@ -574,7 +661,7 @@ function checkCells(planned, domain, notes) {
|
|
|
574
661
|
notes.push(
|
|
575
662
|
note(
|
|
576
663
|
PAJEK_LOSS.NONFINITE_AS_TEXT,
|
|
577
|
-
`${nonFinite} non-finite value(
|
|
664
|
+
`${nonFinite} non-finite value${plural(nonFinite)} of ${domain} column "${name}" ${agree(nonFinite, "is", "are")} written as text`,
|
|
578
665
|
name,
|
|
579
666
|
nonFinite
|
|
580
667
|
)
|
|
@@ -605,9 +692,6 @@ function labelOf(labels, ids, i, needed) {
|
|
|
605
692
|
}
|
|
606
693
|
return null;
|
|
607
694
|
}
|
|
608
|
-
function idText(id) {
|
|
609
|
-
return typeof id === "number" ? formatF64(id) : id;
|
|
610
|
-
}
|
|
611
695
|
function spellsText(column, row) {
|
|
612
696
|
if (column.dtype !== "list" || !column.isSet(row)) {
|
|
613
697
|
return null;
|
|
@@ -670,8 +754,8 @@ function* writeParts(snapshot, options) {
|
|
|
670
754
|
});
|
|
671
755
|
}
|
|
672
756
|
}
|
|
673
|
-
if (options.networkHeader
|
|
674
|
-
yield `*Network ${
|
|
757
|
+
if (options.networkHeader) {
|
|
758
|
+
yield options.name === null ? "*Network\n" : `*Network ${options.name}
|
|
675
759
|
`;
|
|
676
760
|
}
|
|
677
761
|
const firstMode = firstModeOf(snapshot);
|
|
@@ -706,7 +790,7 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
|
|
|
706
790
|
notes.push(
|
|
707
791
|
note(
|
|
708
792
|
PAJEK_LOSS.TEXT,
|
|
709
|
-
`${badText} node id(
|
|
793
|
+
`${badText} node id${plural(badText)} ${agree(badText, "holds", "hold")} a double quote or a line break; Pajek cannot write them as labels or parameters`,
|
|
710
794
|
null,
|
|
711
795
|
badText
|
|
712
796
|
)
|
|
@@ -716,7 +800,7 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
|
|
|
716
800
|
notes.push(
|
|
717
801
|
note(
|
|
718
802
|
PAJEK_LOSS.ID_TEXT_TYPE,
|
|
719
|
-
`${typeChanged} original id(
|
|
803
|
+
`${typeChanged} original id${plural(typeChanged)} ${agree(typeChanged, "reads", "read")} back from ${ORIGINAL_ID_KEY} as the other type under ids: "canonical" (a string "1" becomes 1, a number 1.5 becomes "1.5")`,
|
|
720
804
|
null,
|
|
721
805
|
typeChanged
|
|
722
806
|
)
|
|
@@ -879,7 +963,7 @@ function* writeLines(snapshot, edgePlan) {
|
|
|
879
963
|
yield snapshot.directed ? "*Arcs\n" : "*Edges\n";
|
|
880
964
|
}
|
|
881
965
|
}
|
|
882
|
-
function resolvePajekOptions(options) {
|
|
966
|
+
function resolvePajekOptions(snapshot, options) {
|
|
883
967
|
const common = resolveExportOptions(options);
|
|
884
968
|
const value = options?.networkHeader;
|
|
885
969
|
if (value !== void 0 && typeof value !== "boolean") {
|
|
@@ -888,10 +972,22 @@ function resolvePajekOptions(options) {
|
|
|
888
972
|
found: typeof value
|
|
889
973
|
});
|
|
890
974
|
}
|
|
891
|
-
|
|
975
|
+
const name = options?.name;
|
|
976
|
+
if (name !== void 0 && (typeof name !== "string" || /[\r\n]/.test(name))) {
|
|
977
|
+
throw new GraphFormatError("E_UNSUPPORTED", "option name: not a one-line string", {
|
|
978
|
+
option: "name",
|
|
979
|
+
found: typeof name
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
networkHeader: value ?? name !== void 0,
|
|
984
|
+
name: name ?? snapshot.meta.name,
|
|
985
|
+
mangle: common.sanitizeIds === "mangle"
|
|
986
|
+
};
|
|
892
987
|
}
|
|
893
988
|
const pajekExporter = Object.freeze({
|
|
894
989
|
format: "pajek",
|
|
990
|
+
options: Object.freeze(["name", "networkHeader"]),
|
|
895
991
|
capabilities: CAPABILITIES,
|
|
896
992
|
/**
|
|
897
993
|
* Pre-flight: the generic capability gaps plus the Pajek-specific ones.
|
|
@@ -901,7 +997,7 @@ const pajekExporter = Object.freeze({
|
|
|
901
997
|
*/
|
|
902
998
|
check(snapshot, options) {
|
|
903
999
|
const resolved = resolveExportOptions(options);
|
|
904
|
-
const { mangle } = resolvePajekOptions(options);
|
|
1000
|
+
const { mangle } = resolvePajekOptions(snapshot, options);
|
|
905
1001
|
const notes = [];
|
|
906
1002
|
const planned = plan(snapshot.nodes, "node", notes);
|
|
907
1003
|
const nodePlan = withoutReservedKey(planned, mangle);
|
|
@@ -971,7 +1067,7 @@ const pajekExporter = Object.freeze({
|
|
|
971
1067
|
notes.push(
|
|
972
1068
|
note(
|
|
973
1069
|
PAJEK_LOSS.MUTUAL_AS_UNDIRECTED,
|
|
974
|
-
`${folding.mutualCount} mutual pair(
|
|
1070
|
+
`${folding.mutualCount} mutual pair${plural(folding.mutualCount)} ${agree(folding.mutualCount, "is", "are")} written as undirected edges; the mutual mark is lost`,
|
|
975
1071
|
snapshot.edges.byRole("mutual")?.meta.name ?? null,
|
|
976
1072
|
folding.mutualCount
|
|
977
1073
|
)
|
|
@@ -994,7 +1090,7 @@ const pajekExporter = Object.freeze({
|
|
|
994
1090
|
* @returns the chunks
|
|
995
1091
|
*/
|
|
996
1092
|
export(snapshot, options) {
|
|
997
|
-
const resolved = resolvePajekOptions(options);
|
|
1093
|
+
const resolved = resolvePajekOptions(snapshot, options);
|
|
998
1094
|
return encodeChunks(writeParts(snapshot, resolved));
|
|
999
1095
|
},
|
|
1000
1096
|
/**
|
|
@@ -1004,32 +1100,47 @@ const pajekExporter = Object.freeze({
|
|
|
1004
1100
|
* @returns the document
|
|
1005
1101
|
*/
|
|
1006
1102
|
exportToString(snapshot, options) {
|
|
1007
|
-
const resolved = resolvePajekOptions(options);
|
|
1103
|
+
const resolved = resolvePajekOptions(snapshot, options);
|
|
1008
1104
|
return joinText(writeParts(snapshot, resolved));
|
|
1009
1105
|
}
|
|
1010
1106
|
});
|
|
1011
1107
|
const PAJEK_ISSUE = Object.freeze({
|
|
1012
|
-
|
|
1108
|
+
...INPUT_ISSUE,
|
|
1109
|
+
...ELEMENT_ISSUE,
|
|
1110
|
+
/** The input is not valid UTF-8. The import stops. */
|
|
1013
1111
|
INVALID_UTF8: INVALID_UTF8_CODE,
|
|
1014
|
-
/**
|
|
1112
|
+
/**
|
|
1113
|
+
* Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's declaration or the
|
|
1114
|
+
* `encoding` option). The import stops.
|
|
1115
|
+
*/
|
|
1015
1116
|
INVALID_ENCODING: INVALID_ENCODING_CODE,
|
|
1016
1117
|
/** Bytes that are not UTF-8 and declare no encoding were read as windows-1252. */
|
|
1017
1118
|
ENCODING_FALLBACK: ENCODING_FALLBACK_CODE,
|
|
1018
1119
|
/** A declared encoding the platform cannot decode was ignored. */
|
|
1019
1120
|
UNKNOWN_ENCODING: UNKNOWN_ENCODING_CODE,
|
|
1020
|
-
/**
|
|
1121
|
+
/** There is no `*Vertices` section: the file is empty or not a Pajek network. The import stops. */
|
|
1021
1122
|
NO_VERTICES: "E_PAJEK_NO_VERTICES",
|
|
1022
|
-
/**
|
|
1123
|
+
/**
|
|
1124
|
+
* `*Vertices` without a vertex count, with a count too large to hold, or with a first-mode count outside 0 to N;
|
|
1125
|
+
* the import stops.
|
|
1126
|
+
*/
|
|
1023
1127
|
VERTICES_COUNT: "E_PAJEK_VERTICES_COUNT",
|
|
1024
|
-
/**
|
|
1128
|
+
/**
|
|
1129
|
+
* The file holds several graphs and only the first was read. It is not added when `graphIndex` or `graphName` chose the graph.
|
|
1130
|
+
* `importAllGraphs()` reads every one.
|
|
1131
|
+
*/
|
|
1025
1132
|
MULTIPLE_GRAPHS: MULTIPLE_GRAPHS_CODE,
|
|
1133
|
+
/** `graphIndex` or `graphName` names no graph of the file; the message lists the graphs it holds. The import stops. */
|
|
1134
|
+
GRAPH_NOT_FOUND: GRAPH_NOT_FOUND_CODE,
|
|
1135
|
+
/** `graphName` matches more than one graph; pass `graphIndex`. The import stops. */
|
|
1136
|
+
AMBIGUOUS_GRAPH_NAME: AMBIGUOUS_GRAPH_NAME_CODE,
|
|
1026
1137
|
/** A data line before the first section header. */
|
|
1027
1138
|
OUTSIDE_SECTION: "E_PAJEK_OUTSIDE_SECTION",
|
|
1028
1139
|
/** A section header the importer cannot parse. */
|
|
1029
1140
|
SYNTAX: SYNTAX_CODE,
|
|
1030
1141
|
/** A double quote not closed before the end of the line. */
|
|
1031
1142
|
UNTERMINATED_QUOTE: "E_PAJEK_UNTERMINATED_QUOTE",
|
|
1032
|
-
/** A vertex line the
|
|
1143
|
+
/** A vertex line that is not in Pajek's vertex syntax; the vertex is skipped. */
|
|
1033
1144
|
VERTEX_LINE: "E_PAJEK_VERTEX_LINE",
|
|
1034
1145
|
/** A vertex number outside the declared range. */
|
|
1035
1146
|
VERTEX_RANGE: "E_PAJEK_VERTEX_RANGE",
|
|
@@ -1037,9 +1148,12 @@ const PAJEK_ISSUE = Object.freeze({
|
|
|
1037
1148
|
VERTEX_COUNT: "W_PAJEK_VERTEX_COUNT",
|
|
1038
1149
|
/** A second line for the same vertex; the later values overwrite. */
|
|
1039
1150
|
DUPLICATE_NODE: DUPLICATE_NODE_CODE,
|
|
1040
|
-
/**
|
|
1151
|
+
/**
|
|
1152
|
+
* A line that is not in Pajek's syntax for its section (an arc, edge, list, matrix row, partition or vector
|
|
1153
|
+
* value); it is skipped.
|
|
1154
|
+
*/
|
|
1041
1155
|
LINE: "E_PAJEK_LINE",
|
|
1042
|
-
/**
|
|
1156
|
+
/** An edge names a vertex number outside the range `*Vertices` declared; the edge is skipped. */
|
|
1043
1157
|
UNKNOWN_NODE: "E_UNKNOWN_NODE",
|
|
1044
1158
|
/** A malformed time interval token. */
|
|
1045
1159
|
INTERVAL: "E_PAJEK_INTERVAL",
|
|
@@ -1051,32 +1165,57 @@ const PAJEK_ISSUE = Object.freeze({
|
|
|
1051
1165
|
OBJECT_COUNT: "E_PAJEK_OBJECT_COUNT",
|
|
1052
1166
|
/** A project-file section (`*Events`, `*Permutation`, ...) the importer does not read; its lines are skipped. */
|
|
1053
1167
|
UNSUPPORTED_SECTION: "W_PAJEK_UNSUPPORTED_SECTION",
|
|
1054
|
-
/**
|
|
1168
|
+
/** A section header has extra words Pajek does not define; they are ignored. */
|
|
1055
1169
|
HEADER_EXTRA: "W_PAJEK_HEADER_EXTRA",
|
|
1056
1170
|
/** The file declares vertices but no line section. */
|
|
1057
1171
|
NO_LINES: "W_PAJEK_NO_LINES",
|
|
1058
|
-
/** Vertex numbering starts at 0 rather than 1. */
|
|
1172
|
+
/** Vertex numbering starts at 0 rather than 1, found by `firstVertex: "auto"` (passing `firstVertex: 0` says so and gives no warning). */
|
|
1059
1173
|
ZERO_BASED: "W_PAJEK_ZERO_BASED",
|
|
1060
1174
|
/** Vertex lines mix two and three coordinates. */
|
|
1061
1175
|
COORD_DIMS: "W_PAJEK_COORD_DIMS",
|
|
1062
1176
|
/** Two vertices share a label under nodeIdFrom "label" and became one node. */
|
|
1063
1177
|
LABEL_MERGED: "W_PAJEK_LABEL_MERGED",
|
|
1064
|
-
/** Two
|
|
1178
|
+
/** Two different labels became the same number because `ids` is "number", so their vertices were merged. */
|
|
1065
1179
|
ID_MERGED: ID_MERGED_CODE,
|
|
1066
|
-
/**
|
|
1180
|
+
/**
|
|
1181
|
+
* Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of
|
|
1182
|
+
* its first values.
|
|
1183
|
+
*/
|
|
1067
1184
|
WIDENING_UNSUPPORTED: WIDENING_UNSUPPORTED_CODE,
|
|
1068
|
-
/** A structural column (label, position, shape, spells, relation) renamed `<name>#<id>` because the name was taken
|
|
1185
|
+
/** A structural column (label, position, shape, spells, relation) renamed `<name>#<id>` because the name was taken. */
|
|
1069
1186
|
COLUMN_RENAMED: RENAMED_CODE,
|
|
1070
|
-
/**
|
|
1187
|
+
/**
|
|
1188
|
+
* You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as
|
|
1189
|
+
* a plain attribute.
|
|
1190
|
+
*/
|
|
1071
1191
|
ROLE_TAKEN: ROLE_TAKEN_CODE,
|
|
1072
1192
|
/** Two vertices carry the same `graphty_originalId` under restoreMangledIds and became one node. */
|
|
1073
1193
|
ORIGINAL_ID_MERGED: "W_PAJEK_ORIGINAL_ID_MERGED",
|
|
1074
1194
|
/** A vertex line's `graphty_originalId` came after a later vertex's line had created it under its number. */
|
|
1075
1195
|
ORIGINAL_ID_UNRESTORED: "W_PAJEK_ORIGINAL_ID_UNRESTORED",
|
|
1076
|
-
/**
|
|
1196
|
+
/** You set an option this format does not use; it had no effect. The message names the option. */
|
|
1077
1197
|
OPTION_IGNORED: OPTION_IGNORED_CODE,
|
|
1078
|
-
/**
|
|
1079
|
-
|
|
1198
|
+
/**
|
|
1199
|
+
* You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,
|
|
1200
|
+
* `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.
|
|
1201
|
+
*/
|
|
1202
|
+
SINK_OPTION: SINK_OPTION_CODE,
|
|
1203
|
+
/** A double quote inside a token (a CSV-style doubled quote, a quote mid-word): removed and the parts joined. */
|
|
1204
|
+
QUOTE_IN_TOKEN: "W_PAJEK_QUOTE_IN_TOKEN",
|
|
1205
|
+
/** The same parameter twice on one line; the later value stands. */
|
|
1206
|
+
DUPLICATE_ATTRIBUTE: DUPLICATE_ATTRIBUTE_CODE,
|
|
1207
|
+
/** A character reference beyond U+10FFFF in a label; kept as written. */
|
|
1208
|
+
REFERENCE_RANGE: "W_PAJEK_REFERENCE_RANGE",
|
|
1209
|
+
/** A line of a two-mode network whose endpoints are both in one mode. */
|
|
1210
|
+
TWO_MODE_LINE: "W_PAJEK_TWO_MODE_LINE",
|
|
1211
|
+
/** A bare non-integer number read as a vertex label before two coordinates (`1 0.1 0.2 0.3`); it may be an x y z line without a label. */
|
|
1212
|
+
NUMERIC_LABEL: "W_PAJEK_NUMERIC_LABEL",
|
|
1213
|
+
/** A relation number given a second name by a later `*Arcs :k "name"` header. */
|
|
1214
|
+
RELATION_RENAMED: "W_PAJEK_RELATION_RENAMED",
|
|
1215
|
+
/** A negative vertex number in an adjacency list, read as its absolute value. */
|
|
1216
|
+
NEGATIVE_LIST_ENTRY: "W_PAJEK_NEGATIVE_LIST_ENTRY",
|
|
1217
|
+
/** An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: "string"` to keep every digit. */
|
|
1218
|
+
PRECISION: PRECISION_CODE
|
|
1080
1219
|
});
|
|
1081
1220
|
const USED_OPTIONS = /* @__PURE__ */ new Set([
|
|
1082
1221
|
"ids",
|
|
@@ -1096,6 +1235,8 @@ const USED_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
1096
1235
|
const DEFAULTS = { ids: "canonical", defaultDirected: true, weightFrom: VALUE_FIELD };
|
|
1097
1236
|
const ABORT_CHECK_INTERVAL = 64;
|
|
1098
1237
|
const FIRST_VERTEX_VALUES = /* @__PURE__ */ new Set([0, 1, "auto"]);
|
|
1238
|
+
const NUMERAL = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
|
|
1239
|
+
const NON_FINITE_WORD = /^[+-]?(?:nan|inf|infinity)$/i;
|
|
1099
1240
|
const LABEL_DECL = {
|
|
1100
1241
|
name: LABEL_COLUMN,
|
|
1101
1242
|
dtype: "string",
|
|
@@ -1169,6 +1310,7 @@ class PajekParser {
|
|
|
1169
1310
|
this.kind = "directed";
|
|
1170
1311
|
this.relation = null;
|
|
1171
1312
|
this.vertexCount = -1;
|
|
1313
|
+
this.verticesLine = 0;
|
|
1172
1314
|
this.firstMode = null;
|
|
1173
1315
|
this.networkName = null;
|
|
1174
1316
|
this.base = 1;
|
|
@@ -1181,6 +1323,8 @@ class PajekParser {
|
|
|
1181
1323
|
this.relationNames = /* @__PURE__ */ new Map();
|
|
1182
1324
|
this.objects = [];
|
|
1183
1325
|
this.objectHeader = false;
|
|
1326
|
+
this.firstUnsupported = null;
|
|
1327
|
+
this.outOfRange = 0;
|
|
1184
1328
|
this.indexOfPos = new Uint32Array(0);
|
|
1185
1329
|
this.idOfPos = null;
|
|
1186
1330
|
this.seen = new Uint8Array(0);
|
|
@@ -1241,7 +1385,7 @@ class PajekParser {
|
|
|
1241
1385
|
this.matrixLine(text, line);
|
|
1242
1386
|
return false;
|
|
1243
1387
|
case "object":
|
|
1244
|
-
this.objectLine(text);
|
|
1388
|
+
this.objectLine(text, line);
|
|
1245
1389
|
return false;
|
|
1246
1390
|
case "skip":
|
|
1247
1391
|
return false;
|
|
@@ -1265,7 +1409,8 @@ class PajekParser {
|
|
|
1265
1409
|
*/
|
|
1266
1410
|
finish() {
|
|
1267
1411
|
if (this.vertexCount < 0) {
|
|
1268
|
-
this.
|
|
1412
|
+
const seen = this.firstUnsupported === null ? "" : ` (the file has the unrecognised section *${this.firstUnsupported})`;
|
|
1413
|
+
this.report.fail(PAJEK_ISSUE.NO_VERTICES, `not a Pajek network: no *Vertices section found${seen}`);
|
|
1269
1414
|
}
|
|
1270
1415
|
this.endSection();
|
|
1271
1416
|
this.finishVertices();
|
|
@@ -1284,7 +1429,7 @@ class PajekParser {
|
|
|
1284
1429
|
this.report.warning(
|
|
1285
1430
|
"coercion",
|
|
1286
1431
|
PAJEK_ISSUE.ID_MERGED,
|
|
1287
|
-
`${this.coercer.mergeCount} label(
|
|
1432
|
+
`${this.coercer.mergeCount} label${plural(this.coercer.mergeCount)} merged into an id another label already produced under ids "number"`
|
|
1288
1433
|
);
|
|
1289
1434
|
}
|
|
1290
1435
|
const pajek = {
|
|
@@ -1336,7 +1481,7 @@ class PajekParser {
|
|
|
1336
1481
|
this.report.error(
|
|
1337
1482
|
"validation-error",
|
|
1338
1483
|
PAJEK_ISSUE.OBJECT_COUNT,
|
|
1339
|
-
`*${partition ? "Partition" : "Vector"} "${object.name}" declares ${declared} vertices and holds ${object.values.length} value(
|
|
1484
|
+
`*${partition ? "Partition" : "Vector"} "${object.name}" declares ${declared} vertices and holds ${object.values.length} value${plural(object.values.length)}; the network has ${this.vertexCount}`,
|
|
1340
1485
|
where
|
|
1341
1486
|
);
|
|
1342
1487
|
}
|
|
@@ -1363,7 +1508,7 @@ class PajekParser {
|
|
|
1363
1508
|
this.report.warning(
|
|
1364
1509
|
"validation-error",
|
|
1365
1510
|
PAJEK_ISSUE.HEADER_EXTRA,
|
|
1366
|
-
`ignored ${h.extra.length} unexpected token(
|
|
1511
|
+
`ignored ${h.extra.length} unexpected token${plural(h.extra.length)} after *${h.keyword}: ${h.extra.join(" ")}`,
|
|
1367
1512
|
{ line }
|
|
1368
1513
|
);
|
|
1369
1514
|
}
|
|
@@ -1410,7 +1555,8 @@ class PajekParser {
|
|
|
1410
1555
|
return;
|
|
1411
1556
|
case "unsupported":
|
|
1412
1557
|
this.section = "skip";
|
|
1413
|
-
this.objectHeader =
|
|
1558
|
+
this.objectHeader = isProjectObject(h.keyword);
|
|
1559
|
+
this.firstUnsupported ??= h.keyword;
|
|
1414
1560
|
this.report.warning(
|
|
1415
1561
|
"unsupported",
|
|
1416
1562
|
PAJEK_ISSUE.UNSUPPORTED_SECTION,
|
|
@@ -1456,6 +1602,7 @@ class PajekParser {
|
|
|
1456
1602
|
);
|
|
1457
1603
|
}
|
|
1458
1604
|
this.vertexCount = h.count;
|
|
1605
|
+
this.verticesLine = line;
|
|
1459
1606
|
if (h.secondCount !== null) {
|
|
1460
1607
|
this.firstMode = h.secondCount;
|
|
1461
1608
|
}
|
|
@@ -1496,7 +1643,17 @@ class PajekParser {
|
|
|
1496
1643
|
this.kind = kind;
|
|
1497
1644
|
this.relation = h.relation === null ? null : h.name ?? String(h.relation);
|
|
1498
1645
|
if (h.relation !== null) {
|
|
1499
|
-
|
|
1646
|
+
const name = this.relation ?? String(h.relation);
|
|
1647
|
+
const before = this.relationNames.get(h.relation);
|
|
1648
|
+
if (before !== void 0 && before !== name) {
|
|
1649
|
+
this.report.warning(
|
|
1650
|
+
"validation-error",
|
|
1651
|
+
PAJEK_ISSUE.RELATION_RENAMED,
|
|
1652
|
+
`relation ${h.relation} was named ${JSON.stringify(before)} and is now named ${JSON.stringify(name)}; its lines carry the name of their own section`,
|
|
1653
|
+
{ line, element: String(h.relation) }
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
this.relationNames.set(h.relation, name);
|
|
1500
1657
|
}
|
|
1501
1658
|
}
|
|
1502
1659
|
/**
|
|
@@ -1508,7 +1665,7 @@ class PajekParser {
|
|
|
1508
1665
|
this.report.error(
|
|
1509
1666
|
"validation-error",
|
|
1510
1667
|
PAJEK_ISSUE.MATRIX_ROWS,
|
|
1511
|
-
`*Matrix has ${this.matrixRows} row(
|
|
1668
|
+
`*Matrix has ${this.matrixRows} row${plural(this.matrixRows)}; *Vertices declares ${rows}`
|
|
1512
1669
|
);
|
|
1513
1670
|
}
|
|
1514
1671
|
this.section = "none";
|
|
@@ -1523,7 +1680,7 @@ class PajekParser {
|
|
|
1523
1680
|
setBase(base, line) {
|
|
1524
1681
|
this.base = base;
|
|
1525
1682
|
this.baseKnown = true;
|
|
1526
|
-
if (base === 0) {
|
|
1683
|
+
if (base === 0 && this.firstVertex === "auto") {
|
|
1527
1684
|
this.report.warning(
|
|
1528
1685
|
"coercion",
|
|
1529
1686
|
PAJEK_ISSUE.ZERO_BASED,
|
|
@@ -1543,12 +1700,32 @@ class PajekParser {
|
|
|
1543
1700
|
}
|
|
1544
1701
|
this.nodesCreated = true;
|
|
1545
1702
|
const n = this.vertexCount;
|
|
1546
|
-
const { sink } = this;
|
|
1547
1703
|
for (let pos = 0; pos < n; pos++) {
|
|
1548
|
-
this.indexOfPos[pos] =
|
|
1704
|
+
this.indexOfPos[pos] = this.addNode(this.idOfNumber(pos + this.base));
|
|
1549
1705
|
}
|
|
1550
1706
|
this.report.counts.nodes += n;
|
|
1551
1707
|
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Add a vertex to the sink. A sink that cannot hold the declared vertex set (the builder's
|
|
1710
|
+
* E_TOO_LARGE id map limit) makes the file unreadable, so its refusal is fatal; any other
|
|
1711
|
+
* error passes to the caller.
|
|
1712
|
+
* @param id - the vertex id
|
|
1713
|
+
* @returns the node index
|
|
1714
|
+
*/
|
|
1715
|
+
addNode(id) {
|
|
1716
|
+
try {
|
|
1717
|
+
return this.sink.addNode(id);
|
|
1718
|
+
} catch (err) {
|
|
1719
|
+
if (!(err instanceof GraphFormatError) || err.code !== "E_TOO_LARGE") {
|
|
1720
|
+
throw err;
|
|
1721
|
+
}
|
|
1722
|
+
return this.report.fail(
|
|
1723
|
+
PAJEK_ISSUE.VERTICES_COUNT,
|
|
1724
|
+
`*Vertices ${this.vertexCount}: the sink cannot hold that many (${err.message})`,
|
|
1725
|
+
{ line: this.verticesLine }
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1552
1729
|
/**
|
|
1553
1730
|
* The id of a vertex number under nodeIdFrom "id" (the number coerced by the ids rule) or
|
|
1554
1731
|
* "index" (the position).
|
|
@@ -1603,12 +1780,12 @@ class PajekParser {
|
|
|
1603
1780
|
}
|
|
1604
1781
|
}
|
|
1605
1782
|
}
|
|
1606
|
-
const lines = this.seenCount + this.report.counts.skippedNodes;
|
|
1783
|
+
const lines = this.seenCount + this.report.counts.skippedNodes - this.outOfRange;
|
|
1607
1784
|
if (this.seenCount > 0 && lines < n) {
|
|
1608
1785
|
this.report.warning(
|
|
1609
1786
|
"validation-error",
|
|
1610
1787
|
PAJEK_ISSUE.VERTEX_COUNT,
|
|
1611
|
-
`*Vertices declares ${n} vertices but ${lines} vertex line(
|
|
1788
|
+
`*Vertices declares ${n} vertices but ${lines} vertex line${plural(lines)} ${agree(lines, "was", "were")} read; the others have no label`
|
|
1612
1789
|
);
|
|
1613
1790
|
}
|
|
1614
1791
|
}
|
|
@@ -1618,7 +1795,7 @@ class PajekParser {
|
|
|
1618
1795
|
* @param line - the line number
|
|
1619
1796
|
*/
|
|
1620
1797
|
vertexLine(text, line) {
|
|
1621
|
-
const tokens = this.tokens(text, "node");
|
|
1798
|
+
const tokens = this.tokens(text, "node", line);
|
|
1622
1799
|
if (!isVertexNumber(tokens[0])) {
|
|
1623
1800
|
this.report.counts.skippedNodes++;
|
|
1624
1801
|
throw new LineError(
|
|
@@ -1634,6 +1811,7 @@ class PajekParser {
|
|
|
1634
1811
|
const pos = k - this.base;
|
|
1635
1812
|
if (pos < 0 || pos >= this.vertexCount) {
|
|
1636
1813
|
this.report.counts.skippedNodes++;
|
|
1814
|
+
this.outOfRange++;
|
|
1637
1815
|
throw new LineError(
|
|
1638
1816
|
"validation-error",
|
|
1639
1817
|
PAJEK_ISSUE.VERTEX_RANGE,
|
|
@@ -1643,7 +1821,7 @@ class PajekParser {
|
|
|
1643
1821
|
let i = 1;
|
|
1644
1822
|
let label = null;
|
|
1645
1823
|
if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
|
|
1646
|
-
label =
|
|
1824
|
+
label = this.labelOf(tokens[1], k, line);
|
|
1647
1825
|
i = 2;
|
|
1648
1826
|
}
|
|
1649
1827
|
let x = 0;
|
|
@@ -1668,12 +1846,13 @@ class PajekParser {
|
|
|
1668
1846
|
`vertex ${k}: a single coordinate "${tokens[i]}"; coordinates are x y [z]`
|
|
1669
1847
|
);
|
|
1670
1848
|
}
|
|
1849
|
+
this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
|
|
1671
1850
|
let shape = null;
|
|
1672
1851
|
if (i < tokens.length && isShapeKeyword(tokens[i])) {
|
|
1673
1852
|
shape = tokens[i].toLowerCase();
|
|
1674
1853
|
i++;
|
|
1675
1854
|
}
|
|
1676
|
-
const extras = this.extras(tokens, i, "node");
|
|
1855
|
+
const extras = this.extras(tokens, i, "node", line);
|
|
1677
1856
|
const restored = this.restoredId(extras);
|
|
1678
1857
|
this.createNodes();
|
|
1679
1858
|
const repeated = this.seen[pos] !== 0;
|
|
@@ -1720,18 +1899,7 @@ class PajekParser {
|
|
|
1720
1899
|
sink.setNodeValue(this.labelHandle, index, label);
|
|
1721
1900
|
}
|
|
1722
1901
|
if (dims > 0) {
|
|
1723
|
-
|
|
1724
|
-
this.coordDims = dims;
|
|
1725
|
-
this.positionHandle = declareResolved(sink, "node", positionDecl(dims), this.report, { line }).handle;
|
|
1726
|
-
} else if (dims !== this.coordDims) {
|
|
1727
|
-
this.report.warnOnce(
|
|
1728
|
-
"validation-error",
|
|
1729
|
-
PAJEK_ISSUE.COORD_DIMS,
|
|
1730
|
-
`vertex lines mix ${this.coordDims} and ${dims} coordinates; the position column records sourceDims ${this.coordDims}`,
|
|
1731
|
-
{ line, element: String(k) }
|
|
1732
|
-
);
|
|
1733
|
-
}
|
|
1734
|
-
sink.setNodeValue(this.positionHandle, index, [x, y, z]);
|
|
1902
|
+
this.writePosition(index, dims, [x, y, z], k, line);
|
|
1735
1903
|
}
|
|
1736
1904
|
if (shape !== null) {
|
|
1737
1905
|
if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
|
|
@@ -1753,6 +1921,85 @@ class PajekParser {
|
|
|
1753
1921
|
sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
|
|
1754
1922
|
}
|
|
1755
1923
|
}
|
|
1924
|
+
/**
|
|
1925
|
+
* A vertex label as written, its character references decoded.
|
|
1926
|
+
* @param token - the label token
|
|
1927
|
+
* @param k - the vertex number
|
|
1928
|
+
* @param line - the line number
|
|
1929
|
+
* @returns the label
|
|
1930
|
+
*/
|
|
1931
|
+
labelOf(token, k, line) {
|
|
1932
|
+
return decodeCharacterReferences(token, (reference) => {
|
|
1933
|
+
this.report.warnOnce(
|
|
1934
|
+
"validation-error",
|
|
1935
|
+
PAJEK_ISSUE.REFERENCE_RANGE,
|
|
1936
|
+
`character reference ${reference} is beyond U+10FFFF; it is kept as written`,
|
|
1937
|
+
{ line, element: String(k) },
|
|
1938
|
+
`${PAJEK_ISSUE.REFERENCE_RANGE}:${reference}`
|
|
1939
|
+
);
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Check the token after a vertex line's coordinates (or where they would stand): a numeral the
|
|
1944
|
+
* number range cannot hold is a broken coordinate, never a parameter named "1e999" or "NaN";
|
|
1945
|
+
* and a bare non-integer label before two coordinates may be the x of an x y z line.
|
|
1946
|
+
* @param text - the line
|
|
1947
|
+
* @param tokens - its tokens
|
|
1948
|
+
* @param i - the index after the coordinates
|
|
1949
|
+
* @param labelAndXy - whether the line was read as a label and two coordinates
|
|
1950
|
+
* @param k - the vertex number
|
|
1951
|
+
* @param line - the line number
|
|
1952
|
+
*/
|
|
1953
|
+
checkCoordinates(text, tokens, i, labelAndXy, k, line) {
|
|
1954
|
+
if (i < tokens.length && (NUMERAL.test(tokens[i]) || NON_FINITE_WORD.test(tokens[i])) && !isNumericText(tokens[i])) {
|
|
1955
|
+
this.report.counts.skippedNodes++;
|
|
1956
|
+
throw new LineError(
|
|
1957
|
+
"parse-error",
|
|
1958
|
+
PAJEK_ISSUE.VERTEX_LINE,
|
|
1959
|
+
`vertex ${k}: coordinate "${tokens[i]}" is not a finite number`
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
const label = tokens[1];
|
|
1963
|
+
if (labelAndXy && isNumericText(label) && !Number.isInteger(Number(label)) && !quotedAfterNumber(text, tokens)) {
|
|
1964
|
+
this.report.warnOnce(
|
|
1965
|
+
"validation-error",
|
|
1966
|
+
PAJEK_ISSUE.NUMERIC_LABEL,
|
|
1967
|
+
`vertex ${k}: "${label} ${tokens[2]} ${tokens[3]}" is read as the label ${label} and x y; quote the label, or it may be meant as x y z`,
|
|
1968
|
+
{ line, element: String(k) }
|
|
1969
|
+
);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
/**
|
|
1973
|
+
* Write a vertex's coordinates into the position column (f32 x 3), declared on first use.
|
|
1974
|
+
* @param index - the node index
|
|
1975
|
+
* @param dims - 2 or 3, the coordinates the line gave
|
|
1976
|
+
* @param point - x, y, z (0 when absent)
|
|
1977
|
+
* @param k - the vertex number
|
|
1978
|
+
* @param line - the line number
|
|
1979
|
+
*/
|
|
1980
|
+
writePosition(index, dims, point, k, line) {
|
|
1981
|
+
if (this.positionHandle === INVALID_INDEX) {
|
|
1982
|
+
this.coordDims = dims;
|
|
1983
|
+
this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims), this.report, { line }).handle;
|
|
1984
|
+
} else if (dims !== this.coordDims) {
|
|
1985
|
+
this.report.warnOnce(
|
|
1986
|
+
"validation-error",
|
|
1987
|
+
PAJEK_ISSUE.COORD_DIMS,
|
|
1988
|
+
`vertex lines mix ${this.coordDims} and ${dims} coordinates; the position column records sourceDims ${this.coordDims}`,
|
|
1989
|
+
{ line, element: String(k) }
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
if (!point.every(survivesF32)) {
|
|
1993
|
+
this.report.warnOnce(
|
|
1994
|
+
"precision",
|
|
1995
|
+
PAJEK_ISSUE.PRECISION,
|
|
1996
|
+
`vertex ${k} has a coordinate the f32 position column rounds (warned once)`,
|
|
1997
|
+
{ line, element: String(k) },
|
|
1998
|
+
`${PAJEK_ISSUE.PRECISION}:position`
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
2001
|
+
this.sink.setNodeValue(this.positionHandle, index, point);
|
|
2002
|
+
}
|
|
1756
2003
|
/**
|
|
1757
2004
|
* Whether a `graphty_originalId` parameter is restored as the vertex id: restoreMangledIds
|
|
1758
2005
|
* under nodeIdFrom "id" (under "label" / "index" the parameter stays an ordinary column).
|
|
@@ -1770,7 +2017,7 @@ class PajekParser {
|
|
|
1770
2017
|
numberedNode(ids, pos) {
|
|
1771
2018
|
const id = this.idOfNumber(pos + this.base);
|
|
1772
2019
|
ids[pos] = id;
|
|
1773
|
-
this.indexOfPos[pos] = this.
|
|
2020
|
+
this.indexOfPos[pos] = this.addNode(id);
|
|
1774
2021
|
this.report.counts.nodes++;
|
|
1775
2022
|
}
|
|
1776
2023
|
/**
|
|
@@ -1807,7 +2054,7 @@ class PajekParser {
|
|
|
1807
2054
|
deferredNode(ids, pos, k, text, line, from) {
|
|
1808
2055
|
const id = text === null ? this.idOfNumber(k) : this.coercer.text(text);
|
|
1809
2056
|
const before = this.sink.indexOf(id);
|
|
1810
|
-
const index = this.
|
|
2057
|
+
const index = this.addNode(id);
|
|
1811
2058
|
ids[pos] = id;
|
|
1812
2059
|
this.indexOfPos[pos] = index;
|
|
1813
2060
|
this.report.counts.nodes++;
|
|
@@ -1828,7 +2075,7 @@ class PajekParser {
|
|
|
1828
2075
|
* @param line - the line number
|
|
1829
2076
|
*/
|
|
1830
2077
|
edgeLine(text, line) {
|
|
1831
|
-
let tokens = this.tokens(text, "edge");
|
|
2078
|
+
let tokens = this.tokens(text, "edge", line);
|
|
1832
2079
|
let { relation } = this;
|
|
1833
2080
|
const prefix = RELATION_PREFIX.exec(tokens[0]);
|
|
1834
2081
|
if (prefix !== null) {
|
|
@@ -1852,7 +2099,7 @@ class PajekParser {
|
|
|
1852
2099
|
valueText = tokens[i];
|
|
1853
2100
|
i++;
|
|
1854
2101
|
}
|
|
1855
|
-
const extras = this.extras(tokens, i, "edge");
|
|
2102
|
+
const extras = this.extras(tokens, i, "edge", line);
|
|
1856
2103
|
const { weightFrom } = this.options;
|
|
1857
2104
|
let weight;
|
|
1858
2105
|
let valueIsWeight = false;
|
|
@@ -1882,7 +2129,7 @@ class PajekParser {
|
|
|
1882
2129
|
* @param line - the line number
|
|
1883
2130
|
*/
|
|
1884
2131
|
listLine(text, line) {
|
|
1885
|
-
const tokens = this.tokens(text, "edge");
|
|
2132
|
+
const tokens = this.tokens(text, "edge", line);
|
|
1886
2133
|
for (const token of tokens) {
|
|
1887
2134
|
if (!LIST_VERTEX.test(token)) {
|
|
1888
2135
|
this.report.counts.skippedEdges++;
|
|
@@ -1893,6 +2140,14 @@ class PajekParser {
|
|
|
1893
2140
|
);
|
|
1894
2141
|
}
|
|
1895
2142
|
}
|
|
2143
|
+
if (tokens.some((token) => token.startsWith("-"))) {
|
|
2144
|
+
this.report.warnOnce(
|
|
2145
|
+
"coercion",
|
|
2146
|
+
PAJEK_ISSUE.NEGATIVE_LIST_ENTRY,
|
|
2147
|
+
"an adjacency list holds a negative vertex number; it is read as its absolute value and the sign is dropped",
|
|
2148
|
+
{ line }
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
1896
2151
|
const u = this.endpoint(Math.abs(Number(tokens[0])));
|
|
1897
2152
|
for (let i = 1; i < tokens.length; i++) {
|
|
1898
2153
|
const v = this.endpoint(Math.abs(Number(tokens[i])));
|
|
@@ -1908,7 +2163,7 @@ class PajekParser {
|
|
|
1908
2163
|
* @param line - the line number
|
|
1909
2164
|
*/
|
|
1910
2165
|
matrixLine(text, line) {
|
|
1911
|
-
const tokens = this.tokens(text, "edge");
|
|
2166
|
+
const tokens = this.tokens(text, "edge", line);
|
|
1912
2167
|
const row = this.matrixRows;
|
|
1913
2168
|
this.matrixRows++;
|
|
1914
2169
|
const offset = this.firstMode ?? 0;
|
|
@@ -1918,14 +2173,14 @@ class PajekParser {
|
|
|
1918
2173
|
throw new LineError(
|
|
1919
2174
|
"validation-error",
|
|
1920
2175
|
PAJEK_ISSUE.MATRIX_ROWS,
|
|
1921
|
-
`*Matrix row ${row + 1} is beyond the ${rows} declared row(
|
|
2176
|
+
`*Matrix row ${row + 1} is beyond the ${rows} declared row${plural(rows)}`
|
|
1922
2177
|
);
|
|
1923
2178
|
}
|
|
1924
2179
|
if (tokens.length < columns) {
|
|
1925
2180
|
throw new LineError(
|
|
1926
2181
|
"parse-error",
|
|
1927
2182
|
PAJEK_ISSUE.LINE,
|
|
1928
|
-
`*Matrix row ${row + 1} has ${tokens.length} value(
|
|
2183
|
+
`*Matrix row ${row + 1} has ${tokens.length} value${plural(tokens.length)}; the matrix has ${columns} column${plural(columns)}`
|
|
1929
2184
|
);
|
|
1930
2185
|
}
|
|
1931
2186
|
for (let j = 0; j < columns; j++) {
|
|
@@ -1941,7 +2196,7 @@ class PajekParser {
|
|
|
1941
2196
|
this.report.warnOnce(
|
|
1942
2197
|
"validation-error",
|
|
1943
2198
|
PAJEK_ISSUE.MATRIX_EXTRA,
|
|
1944
|
-
`*Matrix row ${row + 1} has ${tokens.length} value(
|
|
2199
|
+
`*Matrix row ${row + 1} has ${tokens.length} value${plural(tokens.length)} for ${columns} column${plural(columns)}; the extra values are ignored`,
|
|
1945
2200
|
{ line }
|
|
1946
2201
|
);
|
|
1947
2202
|
}
|
|
@@ -1958,10 +2213,11 @@ class PajekParser {
|
|
|
1958
2213
|
* A value line of a `*Partition` (integers) or `*Vector` (numbers): the values of the next
|
|
1959
2214
|
* vertices, usually one per line.
|
|
1960
2215
|
* @param text - the line
|
|
2216
|
+
* @param line - the line number
|
|
1961
2217
|
*/
|
|
1962
|
-
objectLine(text) {
|
|
2218
|
+
objectLine(text, line) {
|
|
1963
2219
|
const object = this.objects[this.objects.length - 1];
|
|
1964
|
-
const tokens = this.tokens(text, "node");
|
|
2220
|
+
const tokens = this.tokens(text, "node", line);
|
|
1965
2221
|
for (const token of tokens) {
|
|
1966
2222
|
if (!isNumericText(token) || object.kind === "partition" && !isI32(Number(token))) {
|
|
1967
2223
|
object.values.push(null);
|
|
@@ -1990,6 +2246,14 @@ class PajekParser {
|
|
|
1990
2246
|
this.directionSet = true;
|
|
1991
2247
|
this.resolver.setHeader(this.kind === "directed", { line });
|
|
1992
2248
|
}
|
|
2249
|
+
if (this.firstMode !== null && u < this.firstMode === v < this.firstMode) {
|
|
2250
|
+
this.report.warnOnce(
|
|
2251
|
+
"validation-error",
|
|
2252
|
+
PAJEK_ISSUE.TWO_MODE_LINE,
|
|
2253
|
+
`a line of the two-mode network joins two vertices of the ${u < this.firstMode ? "first" : "second"} mode`,
|
|
2254
|
+
{ line }
|
|
2255
|
+
);
|
|
2256
|
+
}
|
|
1993
2257
|
const before = sink.edgeCount;
|
|
1994
2258
|
const e = this.resolver.addEdge(this.idAt(u), this.idAt(v), this.kind, weight, { line });
|
|
1995
2259
|
this.report.counts.edges += sink.edgeCount - before;
|
|
@@ -2054,7 +2318,7 @@ class PajekParser {
|
|
|
2054
2318
|
*/
|
|
2055
2319
|
weightOf(text) {
|
|
2056
2320
|
try {
|
|
2057
|
-
return parseWeightText(text);
|
|
2321
|
+
return parseWeightText(text, this.report);
|
|
2058
2322
|
} catch (err) {
|
|
2059
2323
|
this.report.counts.skippedEdges++;
|
|
2060
2324
|
throw err;
|
|
@@ -2065,10 +2329,20 @@ class PajekParser {
|
|
|
2065
2329
|
* Tokenize a data line.
|
|
2066
2330
|
* @param text - the line
|
|
2067
2331
|
* @param domain - what is skipped on an unterminated quote
|
|
2332
|
+
* @param line - the line number
|
|
2068
2333
|
* @returns the tokens (at least one: blank lines never reach here)
|
|
2069
2334
|
*/
|
|
2070
|
-
tokens(text, domain) {
|
|
2071
|
-
const
|
|
2335
|
+
tokens(text, domain, line) {
|
|
2336
|
+
const notes = { oddQuote: false };
|
|
2337
|
+
const tokens = tokenize(text, notes);
|
|
2338
|
+
if (notes.oddQuote) {
|
|
2339
|
+
this.report.warnOnce(
|
|
2340
|
+
"coercion",
|
|
2341
|
+
PAJEK_ISSUE.QUOTE_IN_TOKEN,
|
|
2342
|
+
"a double quote inside a token is removed and the parts joined (Pajek has no escape for a quote)",
|
|
2343
|
+
{ line }
|
|
2344
|
+
);
|
|
2345
|
+
}
|
|
2072
2346
|
if (tokens === null) {
|
|
2073
2347
|
if (domain === "node") {
|
|
2074
2348
|
this.report.counts.skippedNodes++;
|
|
@@ -2085,24 +2359,16 @@ class PajekParser {
|
|
|
2085
2359
|
* @param tokens - the row's tokens
|
|
2086
2360
|
* @param start - the first token to read
|
|
2087
2361
|
* @param domain - what is skipped when the row is malformed
|
|
2362
|
+
* @param line - the line number
|
|
2088
2363
|
* @returns the parsed extras
|
|
2089
2364
|
*/
|
|
2090
|
-
extras(tokens, start, domain) {
|
|
2365
|
+
extras(tokens, start, domain, line) {
|
|
2091
2366
|
const extras = { keys: [], values: [], spells: null };
|
|
2367
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2092
2368
|
for (let i = start; i < tokens.length; ) {
|
|
2093
2369
|
const token = tokens[i];
|
|
2094
|
-
if (
|
|
2095
|
-
|
|
2096
|
-
const spells = parseIntervals(token);
|
|
2097
|
-
extras.spells = spells.length === 0 ? null : spells;
|
|
2098
|
-
} catch (err) {
|
|
2099
|
-
this.skip(domain);
|
|
2100
|
-
throw new LineError(
|
|
2101
|
-
"validation-error",
|
|
2102
|
-
PAJEK_ISSUE.INTERVAL,
|
|
2103
|
-
err instanceof Error ? err.message : String(err)
|
|
2104
|
-
);
|
|
2105
|
-
}
|
|
2370
|
+
if (token.startsWith("[")) {
|
|
2371
|
+
extras.spells = this.intervals(token, domain);
|
|
2106
2372
|
i++;
|
|
2107
2373
|
continue;
|
|
2108
2374
|
}
|
|
@@ -2114,12 +2380,48 @@ class PajekParser {
|
|
|
2114
2380
|
`parameter "${token}" has no value`
|
|
2115
2381
|
);
|
|
2116
2382
|
}
|
|
2383
|
+
if (seen.has(token)) {
|
|
2384
|
+
this.report.warning(
|
|
2385
|
+
"merged",
|
|
2386
|
+
PAJEK_ISSUE.DUPLICATE_ATTRIBUTE,
|
|
2387
|
+
`parameter ${JSON.stringify(token)} is given twice on one line; the later value ${JSON.stringify(tokens[i + 1])} stands`,
|
|
2388
|
+
{ line, element: token }
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
seen.add(token);
|
|
2117
2392
|
extras.keys.push(token);
|
|
2118
2393
|
extras.values.push(tokens[i + 1]);
|
|
2119
2394
|
i += 2;
|
|
2120
2395
|
}
|
|
2121
2396
|
return extras;
|
|
2122
2397
|
}
|
|
2398
|
+
/**
|
|
2399
|
+
* The spells of a row's interval token; a malformed one skips the row.
|
|
2400
|
+
* @param token - the token, starting with "["
|
|
2401
|
+
* @param domain - what is skipped when the token is malformed
|
|
2402
|
+
* @returns the spells, or null for an empty `[]`, which is no spell at all
|
|
2403
|
+
*/
|
|
2404
|
+
intervals(token, domain) {
|
|
2405
|
+
if (!isIntervalToken(token)) {
|
|
2406
|
+
this.skip(domain);
|
|
2407
|
+
throw new LineError(
|
|
2408
|
+
"validation-error",
|
|
2409
|
+
PAJEK_ISSUE.INTERVAL,
|
|
2410
|
+
`time interval ${token} is not closed by "]"`
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
try {
|
|
2414
|
+
const spells = parseIntervals(token);
|
|
2415
|
+
return spells.length === 0 ? null : spells;
|
|
2416
|
+
} catch (err) {
|
|
2417
|
+
this.skip(domain);
|
|
2418
|
+
throw new LineError(
|
|
2419
|
+
"validation-error",
|
|
2420
|
+
PAJEK_ISSUE.INTERVAL,
|
|
2421
|
+
err instanceof Error ? err.message : String(err)
|
|
2422
|
+
);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2123
2425
|
/**
|
|
2124
2426
|
* Count a skipped element.
|
|
2125
2427
|
* @param domain - node or edge
|
|
@@ -2156,7 +2458,7 @@ class PajekParser {
|
|
|
2156
2458
|
}
|
|
2157
2459
|
}
|
|
2158
2460
|
function startsWithCoordinates(text, tokens) {
|
|
2159
|
-
if (text
|
|
2461
|
+
if (quotedAfterNumber(text, tokens)) {
|
|
2160
2462
|
return false;
|
|
2161
2463
|
}
|
|
2162
2464
|
let run = 0;
|
|
@@ -2165,6 +2467,9 @@ function startsWithCoordinates(text, tokens) {
|
|
|
2165
2467
|
}
|
|
2166
2468
|
return run === 2;
|
|
2167
2469
|
}
|
|
2470
|
+
function quotedAfterNumber(text, tokens) {
|
|
2471
|
+
return text.trimStart().slice(tokens[0].length).trimStart().startsWith('"');
|
|
2472
|
+
}
|
|
2168
2473
|
function firstVertexOption(value) {
|
|
2169
2474
|
if (value === void 0) {
|
|
2170
2475
|
return "auto";
|
|
@@ -2181,23 +2486,32 @@ function firstVertexOption(value) {
|
|
|
2181
2486
|
}
|
|
2182
2487
|
);
|
|
2183
2488
|
}
|
|
2184
|
-
|
|
2489
|
+
function headSection(text) {
|
|
2490
|
+
let rest = text.trimStart();
|
|
2491
|
+
while (rest.startsWith("%")) {
|
|
2492
|
+
const end = rest.search(/[\r\n]/);
|
|
2493
|
+
rest = end < 0 ? "" : rest.slice(end).trimStart();
|
|
2494
|
+
}
|
|
2495
|
+
return /^\*(vertices|network)\b/i.exec(rest)?.[1].toLowerCase() ?? null;
|
|
2496
|
+
}
|
|
2185
2497
|
const pajekImporter = Object.freeze({
|
|
2186
2498
|
format: "pajek",
|
|
2499
|
+
options: Object.freeze(["firstVertex"]),
|
|
2187
2500
|
extensions: Object.freeze([".net", ".paj"]),
|
|
2188
2501
|
mimeTypes: Object.freeze(["text/x-pajek", "text/plain"]),
|
|
2189
2502
|
/**
|
|
2190
|
-
* Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`)
|
|
2503
|
+
* Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`),
|
|
2504
|
+
* after any `%` comment lines.
|
|
2191
2505
|
* @param head - the first bytes
|
|
2192
2506
|
* @returns 0.9 for a `*Vertices` start, 0.8 for `*Network`, 0 otherwise
|
|
2193
2507
|
*/
|
|
2194
2508
|
sniff(head) {
|
|
2195
|
-
const text = new TextDecoder("utf-8").decode(head
|
|
2196
|
-
const
|
|
2197
|
-
if (
|
|
2509
|
+
const text = new TextDecoder("utf-8").decode(head);
|
|
2510
|
+
const section = headSection(text.startsWith("\uFEFF") ? text.slice(1) : text);
|
|
2511
|
+
if (section === null) {
|
|
2198
2512
|
return 0;
|
|
2199
2513
|
}
|
|
2200
|
-
return
|
|
2514
|
+
return section === "vertices" ? 0.9 : 0.8;
|
|
2201
2515
|
},
|
|
2202
2516
|
/**
|
|
2203
2517
|
* Read a Pajek network into the sink.
|
|
@@ -2207,6 +2521,9 @@ const pajekImporter = Object.freeze({
|
|
|
2207
2521
|
* @returns the report
|
|
2208
2522
|
*/
|
|
2209
2523
|
async import(input, sink, options) {
|
|
2524
|
+
if (graphChosen(options)) {
|
|
2525
|
+
return importChosenGraph(pajekImporter, input, sink, options);
|
|
2526
|
+
}
|
|
2210
2527
|
const resolved = resolveImportOptions(options, DEFAULTS);
|
|
2211
2528
|
const firstVertex = firstVertexOption(options?.firstVertex);
|
|
2212
2529
|
const report = new ImportReportBuilder("pajek", resolved.errorLimit);
|
|
@@ -2217,7 +2534,8 @@ const pajekImporter = Object.freeze({
|
|
|
2217
2534
|
let rest = null;
|
|
2218
2535
|
let restLine = 0;
|
|
2219
2536
|
let sinceCheck = 0;
|
|
2220
|
-
for await (const
|
|
2537
|
+
for await (const raw of reader) {
|
|
2538
|
+
const text = withoutStrayBom(raw);
|
|
2221
2539
|
if (rest !== null) {
|
|
2222
2540
|
rest.line(text);
|
|
2223
2541
|
} else if (parser.line(text, reader.line)) {
|
|
@@ -2232,10 +2550,11 @@ const pajekImporter = Object.freeze({
|
|
|
2232
2550
|
}
|
|
2233
2551
|
parser.finish();
|
|
2234
2552
|
if (rest !== null) {
|
|
2553
|
+
const objects = rest.objects > 0 ? `; ${rest.objects} *Partition / *Vector object(s) after them are not read` : "";
|
|
2235
2554
|
report.warning(
|
|
2236
2555
|
"unsupported",
|
|
2237
2556
|
PAJEK_ISSUE.MULTIPLE_GRAPHS,
|
|
2238
|
-
`the project file holds ${rest.count} more network(
|
|
2557
|
+
`the project file holds ${rest.count} more network${plural(rest.count)} after the first; the first is read (graphIndex or graphName chooses another; importAllGraphs() reads every one)${objects}`,
|
|
2239
2558
|
{ line: restLine }
|
|
2240
2559
|
);
|
|
2241
2560
|
}
|
|
@@ -2265,7 +2584,8 @@ const pajekImporter = Object.freeze({
|
|
|
2265
2584
|
let parser = open();
|
|
2266
2585
|
const reader = new LineReader(input, reports[0], resolved);
|
|
2267
2586
|
let sinceCheck = 0;
|
|
2268
|
-
for await (const
|
|
2587
|
+
for await (const raw of reader) {
|
|
2588
|
+
const text = withoutStrayBom(raw);
|
|
2269
2589
|
if (parser.line(text, reader.line)) {
|
|
2270
2590
|
parser.finish();
|
|
2271
2591
|
reports.push(new ImportReportBuilder("pajek", resolved.errorLimit));
|
|
@@ -2282,9 +2602,13 @@ const pajekImporter = Object.freeze({
|
|
|
2282
2602
|
return reports.map((r) => r.finish());
|
|
2283
2603
|
}
|
|
2284
2604
|
});
|
|
2605
|
+
function withoutStrayBom(text) {
|
|
2606
|
+
return text.codePointAt(0) === 65279 ? text.slice(1) : text;
|
|
2607
|
+
}
|
|
2285
2608
|
class NetworkCounter {
|
|
2286
2609
|
constructor() {
|
|
2287
2610
|
this.count = 0;
|
|
2611
|
+
this.objects = 0;
|
|
2288
2612
|
this.named = false;
|
|
2289
2613
|
this.populated = false;
|
|
2290
2614
|
this.afterObjectHeader = false;
|
|
@@ -2307,8 +2631,11 @@ class NetworkCounter {
|
|
|
2307
2631
|
return;
|
|
2308
2632
|
}
|
|
2309
2633
|
const { kind } = h;
|
|
2310
|
-
if (kind === "partition" || kind === "vector"
|
|
2634
|
+
if (kind === "partition" || kind === "vector") {
|
|
2311
2635
|
this.afterObjectHeader = true;
|
|
2636
|
+
this.objects++;
|
|
2637
|
+
} else if (kind === "unsupported") {
|
|
2638
|
+
this.afterObjectHeader = isProjectObject(h.keyword);
|
|
2312
2639
|
} else if (kind === "network") {
|
|
2313
2640
|
if (this.count === 0 || this.named || this.populated) {
|
|
2314
2641
|
this.count++;
|
|
@@ -2330,4 +2657,4 @@ export {
|
|
|
2330
2657
|
pajekImporter as b,
|
|
2331
2658
|
pajekExporter as p
|
|
2332
2659
|
};
|
|
2333
|
-
//# sourceMappingURL=importer-
|
|
2660
|
+
//# sourceMappingURL=importer-C_TEA1zJ.js.map
|